# PlotKPC.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 . # -*- coding: utf-8 -*- import logging from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot logger = logging.getLogger() class PlotKPZ(PamhyrPlot): def __init__(self, canvas=None, trad=None, study=None, data=None, toolbar=None, parent=None): self._study = study super(PlotKPZ, self).__init__( canvas=canvas, trad=trad, data=data, toolbar=toolbar, parent=parent ) self._isometric_axis = False self.line_kp_zgl = [] self.line_kp_zmin = None self.line_kp_zmin_zmax = None self.line_kp_zmin_zmax_highlight = None self.label_x = self._trad["unit_kp"] self.label_y = self._trad["unit_height"] self.before_plot_selected = None self.plot_selected = None self.after_plot_selected = None @timer def draw(self): self.init_axes() if self.data is None: return if len(self.data.profiles) == 0: return profiles_defined = any( filter( lambda profile: len(profile) > 0, self.data.profiles ) ) if not profiles_defined: self._init = False return self.draw_z_line() self.draw_z_line_highlight() self.draw_current() self.draw_gl() self.draw_bottom() self.draw_profiles_hs(self._data) self.idle() self._init = True def draw_z_line(self): kp = self.data.get_kp_complete_profiles() z_min = self.data.get_z_min() z_max = self.data.get_z_max() self.line_kp_zmin_zmax = self.canvas.axes.vlines( x=kp, ymin=z_min, ymax=z_max, color=self.color_plot, lw=1. ) def draw_z_line_highlight(self): if self._highlight_data is not None: kp = self.data.get_kp_complete_profiles() z_min = self.data.get_z_min() z_max = self.data.get_z_max() kp_min, kp_max = self._highlight_data indexes = list( map( lambda x: x[0], filter( lambda x: kp_min <= x[1] <= kp_max, enumerate(kp) ) ) ) def indexes_filter(data): return list( map( lambda x: x[1], filter( lambda x: x[0] in indexes, enumerate(data) ) ) ) ikp = indexes_filter(kp) imin = indexes_filter(z_min) imax = indexes_filter(z_max) self.line_kp_zmin_zmax_highlight = self.canvas.axes.vlines( x=ikp, ymin=imin, ymax=imax, color=self.color_plot_highlight, lw=1. ) def draw_current(self): kp = self.data.get_kp_complete_profiles() z_min = self.data.get_z_min() z_max = self.data.get_z_max() self.plot_selected, = self.canvas.axes.plot( (kp[0], kp[0]), (z_min[0], z_max[0]), color=self.color_plot_current, lw=1.5 ) self.plot_selected.set_visible(False) self.before_plot_selected, = self.canvas.axes.plot( (kp[0], kp[0]), (z_min[0], z_max[0]), color=self.color_plot_previous, lw=1.5, linestyle='--' ) self.before_plot_selected.set_visible(False) self.after_plot_selected, = self.canvas.axes.plot( (kp[0], kp[0]), (z_min[0], z_max[0]), color=self.color_plot_next, lw=1.5, linestyle='--' ) self.after_plot_selected.set_visible(False) def draw_gl(self): kp = self.data.get_kp_complete_profiles() ind = 0 self.line_kp_zgl = [] for z in self.data.get_guidelines_z(): # Is incomplete guideline? if len(z) != len(kp): continue self.line_kp_zgl.append( self.canvas.axes.plot( kp, z, lw=1., color=self.colors[ind % len(self.colors)], linestyle=self.linestyle[ind // len(self.colors)] ) ) ind += 1 def draw_bottom(self): kp = self.data.get_kp_complete_profiles() z_min = self.data.get_z_min() self.line_kp_zmin, = self.canvas.axes.plot( kp, z_min, linestyle=":", lw=1.5, color='lightgrey' ) def draw_profiles_hs(self, reach): lhs = filter( lambda hs: hs._input_reach.reach is reach, self._study.river.hydraulic_structures.lst ) for hs in lhs: x = hs.input_kp z_min = reach.get_z_min() z_max = reach.get_z_max() self.canvas.axes.plot( [x, x], [min(z_min), max(z_max)], linestyle="--", lw=1., color=self.color_plot_previous, ) self.canvas.axes.annotate( " > " + hs.name, (x, max(z_max)), horizontalalignment='left', verticalalignment='top', annotation_clip=True, fontsize=9, color=self.color_plot_previous, ) @timer def update(self): if not self._init: self.draw() return self.update_gl() self.update_current() self.update_idle() def update_current(self): if self._current_data_update: ind = self._current_data before = ind - 1 after = ind + 1 self.before_plot_selected.set_visible(False) self.plot_selected.set_visible(False) self.after_plot_selected.set_visible(False) if 0 <= before < self.data.number_profiles: profile = self.data.profile(before) if len(profile) > 0: kp_i = profile.kp z_min_i = profile.z_min() z_max_i = profile.z_max() self.before_plot_selected.set_data( (kp_i, kp_i), (z_min_i, z_max_i) ) self.before_plot_selected.set_visible(True) if 0 <= ind < self.data.number_profiles: profile = self.data.profile(ind) if len(profile) > 0: kp_i = profile.kp z_min_i = profile.z_min() z_max_i = profile.z_max() self.plot_selected.set_data( (kp_i, kp_i), (z_min_i, z_max_i) ) self.plot_selected.set_visible(True) if 0 <= after < self.data.number_profiles: profile = self.data.profile(after) if len(profile) > 0: kp_i = profile.kp z_min_i = profile.z_min() z_max_i = profile.z_max() self.after_plot_selected.set_data( (kp_i, kp_i), (z_min_i, z_max_i) ) self.after_plot_selected.set_visible(True) def update_gl(self): if self._current_data_update: return kp = self.data.get_kp_complete_profiles() z_min = self.data.get_z_min() z_max = self.data.get_z_max() self.line_kp_zmin.set_data(kp, z_min) self.line_kp_zmin_zmax.remove() self.line_kp_zmin_zmax = self.canvas.axes.vlines( x=kp, ymin=z_min, ymax=z_max, color='r', lw=1. ) z_complete = self.data.get_guidelines_z() try: for i in range(len(self.line_kp_zgl)): self.line_kp_zgl[i][0].set_data( kp, z_complete[i] ) except Exception as e: logger.warning(f"Failed to update graphic KPZ: {e}")