# PlotAC.py -- Pamhyr # Copyright (C) 2023-2025 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 -*- from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot from matplotlib import pyplot as plt from PyQt5.QtCore import ( QCoreApplication ) _translate = QCoreApplication.translate class PlotAC(PamhyrPlot): def __init__(self, canvas=None, trad=None, toolbar=None, results=None, reach_id=0, profile_id=[0], res_id=[0], parent=None): super(PlotAC, self).__init__( canvas=canvas, trad=trad, data=results, toolbar=toolbar, parent=parent ) self._current_reach_id = reach_id self._current_profile_id = profile_id self._current_res_id = res_id[0] self._timestamps = parent._timestamps self._current_timestamp = max(self._timestamps) self.label_x = self._trad['x'] self.label_y = self._trad["unit_elevation"] self.label_bottom = self._trad['label_bottom'] self.label_water = self._trad['label_water'] self.label_water_max = self._trad['label_water_max'] self._isometric_axis = False self._auto_relim_update = True self._autoscale_update = True @property def results(self): return self.data @results.setter def results(self, results): self.data = results self._current_timestamp = max(self._timestamps) @timer def draw(self, highlight=None): self.init_axes() if self.results is None: return if self.results[self._current_res_id] is None: return results = self.results[self._current_res_id] reach = results.river.reach(self._current_reach_id) profile = reach.profile(self._current_profile_id) self.draw_profile(reach, profile) self.draw_water_elevation(reach, profile) self.draw_water_elevation_max(reach, profile) self.draw_gl() self.enable_legend() self.idle() self._init = True def draw_profile(self, reach, profile): x = profile.geometry.get_station() z = profile.geometry.z() self.line_rk, = self.canvas.axes.plot( x, z, linestyle="solid", lw=1.5, label=self.label_bottom, color=self.color_plot_river_bottom, ) def draw_water_elevation(self, reach, profile): x = profile.geometry.get_station() z = profile.geometry.z() rk = reach.geometry.get_rk() water_z = profile.get_ts_key(self._current_timestamp, "Z") self.water, = self.canvas.axes.plot( [min(x), max(x)], [water_z, water_z], label=self.label_water, lw=1., color=self.color_plot_river_water, ) self.collection = self.canvas.axes.fill_between( x, z, water_z, where=list(map(lambda x: x <= water_z, z)), color=self.color_plot_river_water_zone, alpha=0.7, interpolate=True ) self.liste_chemins = self.collection.get_paths() def draw_water_elevation_max(self, reach, profile): x = profile.geometry.get_station() z = profile.geometry.z() rk = reach.geometry.get_rk() water_z = max(profile.get_key("Z")) self.water_max, = self.canvas.axes.plot( [min(x), max(x)], [water_z, water_z], label=self.label_water_max, linestyle='dotted', lw=1., color=self.color_plot_river_water, ) def draw_gl(self): results = self.results[self._current_res_id] reach = results.river.reach(self._current_reach_id) profile = reach.profile(self._current_profile_id) if profile is None: return station = profile.geometry.get_station() elevation = profile.geometry.z() gl = profile.geometry.names() self.annotation = [] self.cgl, self.igl = reach.geometry.compute_guidelines() lcomplete = list(self.cgl) lincomplete = list(self.igl) self.color_complete_gl = self.colors self.color_incomplete_gl = 2 * ["grey"] x_gl_complete = [] y_gl_complete = [] x_gl_incomplete = [] y_gl_incomplete = [] for i, txt in enumerate(gl): if txt == "": continue if txt.strip() in self.cgl: color = self.color_complete_gl[ lcomplete.index(txt) % len(self.color_complete_gl) ] else: color = self.color_incomplete_gl[ lincomplete.index(txt) ] annotation = self.canvas.axes.annotate( txt, (station[i], elevation[i]), horizontalalignment='left', verticalalignment='top', annotation_clip=True, fontsize=11, color=color ) annotation.set_position((station[i] + 0., elevation[i] + 0.)) self.annotation.append(annotation) if txt.strip() in self.cgl: x_gl_complete.append(station[i]) y_gl_complete.append(elevation[i]) else: x_gl_incomplete.append(station[i]) y_gl_incomplete.append(elevation[i]) def set_reach(self, reach_id): self._current_reach_id = reach_id self._current_profile_id = 0 self.update() def set_profile(self, profile_id): self._current_profile_id = profile_id self.update() def set_result(self, res_id): self._current_res_id = res_id[0] self.update() def set_timestamp(self, timestamp): self._current_timestamp = timestamp reach = self.results[self._current_res_id].river.reach( self._current_reach_id) profile = reach.profile(self._current_profile_id) x = profile.geometry.get_station() z = profile.geometry.z() self.update_water(reach, profile, x, z) self.update_idle() def update(self): if not self._init: self.draw() reach = self.results[self._current_res_id].river.reach( self._current_reach_id) profile = reach.profile(self._current_profile_id) x = profile.geometry.get_station() z = profile.geometry.z() self.update_river_bottom(reach, profile, x, z) self.update_water(reach, profile, x, z) self.update_water_max(reach, profile, x, z) self.update_gl() self.update_idle() def update_gl(self): for a in self.annotation: a.remove() self.annotation[:] = [] self.draw_gl() def update_river_bottom(self, reach, profile, x, z): self.line_rk.set_data(x, z) def update_water(self, reach, profile, x, z): water_z = profile.get_ts_key(self._current_timestamp, "Z") self.water.set_data( [min(x), max(x)], [water_z, water_z] ) self.collection.remove() self.collection = self.canvas.axes.fill_between( x, z, water_z, where=list(map(lambda x: x <= water_z, z)), color=self.color_plot_river_water_zone, alpha=0.7, interpolate=True ) def update_water_max(self, reach, profile, x, z): water_z = max(profile.get_key("Z")) self.water_max.set_data( [min(x), max(x)], [water_z, water_z] )