# Plot.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 functools import reduce from datetime import datetime from numpy import sqrt from numpy import asarray from tools import timer from View.Tools.PamhyrPlot import PamhyrPlot from View.Results.CustomPlot.Translate import CustomPlotTranslate logger = logging.getLogger() unit = { "bed_elevation": "0-meter", "bed_elevation_envelop": "0-meter", "water_elevation": "0-meter", "water_elevation_envelop": "0-meter", "discharge": "1-m3s", "discharge_envelop": "1-m3s", "velocity": "2-ms", "velocity_envelop": "2-ms", "depth": "3-meter", "depth_envelop": "3-meter", "mean_depth": "3-meter", "froude": "4-dimensionless", "wet_area": "5-m2", } class CustomPlot(PamhyrPlot): def __init__(self, x, y, envelop, reach, profile, timestamp, data=None, canvas=None, trad=None, res_id=0, 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._envelop = envelop self._reach = reach self._profile = profile self._timestamp = timestamp self._current_res_id = res_id self._parent = parent 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 = {} self.lines = {} def draw_bottom_with_bedload(self, reach): self._bedrock = self.sl_compute_bedrock(reach) rk = reach.geometry.get_rk() z = self.sl_compute_current_z(reach) return z def sl_compute_current_z(self, reach): z_br = self._bedrock sl = self.sl_compute_current_rk(reach) z = list( map( lambda z, sl: reduce( lambda z, h: z + h[0], sl, z ), z_br, # Bedrock elevation sl # Current sediment layers ) ) return z def sl_compute_bedrock(self, reach): z_min = reach.geometry.get_z_min() sl = self.sl_compute_initial(reach) z = list( map( lambda z, sl: reduce( lambda z, h: z - h[0], sl, z ), z_min, # Original geometry sl # Original sediment layers ) ) return z def sl_compute_initial(self, reach): """ Get SL list for profile p at initial time (initial data) """ t0 = min(list(self.data[self._current_res_id].get("timestamps"))) return map( lambda p: p.get_ts_key(t0, "sl")[0], reach.profiles ) def sl_compute_current_rk(self, reach): """ Get SL list for profile p at current time """ return map( lambda p: p.get_ts_key(self._timestamp, "sl")[0], reach.profiles ) def get_ts_zmin(self, profile): results = self.data[self._current_res_id] nt = len(list(results.get("timestamps"))) reach = results.river.reach(self._reach) berdrock = self.sl_compute_bedrock(reach) sl = reach.profile(profile).get_key("sl") ts_z_bedrock = [berdrock[profile]]*nt ts_z_min = list( map( lambda z, sl: reduce( lambda z, h: z + h, sl, z ), ts_z_bedrock, # Bedrock elevations asarray(sl)[:, 0, :, 0] # Sediment layers ) ) return ts_z_min def _draw_rk(self): results = self.data[self._current_res_id] reach = results.river.reach(self._reach) if self._current_res_id == 2: # compare results reach1 = self.data[0].river.reach(self._reach) reach2 = self.data[1].river.reach(self._reach) rk = reach.geometry.get_rk() if reach.has_sediment(): z_min = self.draw_bottom_with_bedload(reach) else: z_min = reach.geometry.get_z_min() q = list( map( lambda p: p.get_ts_key(self._timestamp, "Q"), reach.profiles ) ) z = list( map( lambda p: p.get_ts_key(self._timestamp, "Z"), reach.profiles ) ) v = list( map( lambda p: p.get_ts_key(self._timestamp, "V"), reach.profiles ) ) shift = 0 compt = 0 for ax in sorted(self._axes): if compt == 0: self._axes[ax].spines['left'].set_position(('outward', shift)) compt += 1 else: self._axes[ax].spines['right'].set_position(('outward', shift)) shift += 60 if len(self.lines) != 0: self.lines = {} if "bed_elevation" in self._y: ax = self._axes[unit["bed_elevation"]] line = ax.plot( rk, z_min, color='grey', lw=1., ) self.lines["bed_elevation"] = line if self._envelop and reach.has_sediment(): ax = self._axes[unit["bed_elevation_envelop"]] e = list( map( lambda p: max(self.get_ts_zmin(p)), range(len(reach)) ) ) line1 = ax.plot( rk, e, color='grey', lw=1., linestyle='dotted', ) self.lines["bed_elevation_envelop"] = line1 e = list( map( lambda p: min(self.get_ts_zmin(p)), range(len(reach)) ) ) line2 = ax.plot( rk, e, color='grey', lw=1., linestyle='dotted', ) # self.lines["bed_elevation_envelop"] = line2 if "water_elevation" in self._y: ax = self._axes[unit["water_elevation"]] line = ax.plot( rk, z, lw=1., color='blue', ) self.lines["water_elevation"] = line if "bed_elevation" in self._y and self._current_res_id != 2: self.fill = ax.fill_between( rk, z_min, z, color='blue', alpha=0.5, interpolate=True ) if self._envelop: ax = self._axes[unit["water_elevation_envelop"]] d = list( map( lambda p: max(p.get_key("Z")), reach.profiles ) ) line1 = ax.plot( rk, d, lw=1., color='blue', linestyle='dotted', ) self.lines["water_elevation_envelop"] = line1 d = list( map( lambda p: min(p.get_key("Z")), reach.profiles ) ) line2 = ax.plot( rk, d, lw=1., color='blue', linestyle='dotted', ) # self.lines["water_elevation_envelop2"] = line2 if "discharge" in self._y: ax = self._axes[unit["discharge"]] line = ax.plot( rk, q, lw=1., color='r', ) self.lines["discharge"] = line if self._envelop: ax = self._axes[unit["discharge_envelop"]] q1 = list( map( lambda p: max(p.get_key("Q")), reach.profiles ) ) line1 = ax.plot( rk, q1, lw=1., color='r', linestyle='dotted', ) self.lines["discharge_envelop"] = line1 q2 = list( map( lambda p: min(p.get_key("Q")), reach.profiles ) ) line2 = ax.plot( rk, q2, lw=1., color='r', linestyle='dotted', ) # self.lines["discharge_envelop2"] = line2 if "velocity" in self._y: ax = self._axes[unit["velocity"]] line = ax.plot( rk, v, lw=1., color='g', ) self.lines["velocity"] = line if self._envelop: velocities = list( map( lambda p: p.get_key("V"), reach.profiles ) ) ax = self._axes[unit["velocity_envelop"]] vmax = [max(v) for v in velocities] line1 = ax.plot( rk, vmax, lw=1., color='g', linestyle='dotted', ) self.lines["velocity_envelop"] = line1 vmin = [min(v) for v in velocities] line2 = ax.plot( rk, vmin, lw=1., color='g', linestyle='dotted', ) # self.lines["velocity_envelop2"] = line2 if "depth" in self._y: ax = self._axes[unit["depth"]] if self._current_res_id != 2: d = list( map( lambda p: p.geometry.max_water_depth( p.get_ts_key(self._timestamp, "Z")), reach.profiles ) ) else: d1 = list( map( lambda p: p.geometry.max_water_depth( p.get_ts_key(self._timestamp, "Z")), reach1.profiles ) ) d2 = list( map( lambda p: p.geometry.max_water_depth( p.get_ts_key(self._timestamp, "Z")), reach2.profiles ) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( rk, d, color='brown', lw=1., ) self.lines["depth"] = line if self._envelop and self._current_res_id != 2: ax = self._axes[unit["depth_envelop"]] d = list(map( lambda p1, p2: p1 - p2, map( lambda p: max(p.get_key("Z")), reach.profiles ), z_min) ) line1 = ax.plot( rk, d, color='brown', lw=1., linestyle='dotted', ) self.lines["depth_envelop"] = line1 d = list(map( lambda p1, p2: p1 - p2, map( lambda p: min(p.get_key("Z")), reach.profiles ), z_min) ) line2 = ax.plot( rk, d, color='brown', lw=1., linestyle='dotted', ) # self.lines["depth_envelop2"] = line2 if "mean_depth" in self._y: ax = self._axes[unit["mean_depth"]] if self._current_res_id != 2: d = list( map( lambda p: p.geometry.mean_water_depth( p.get_ts_key(self._timestamp, "Z")), reach.profiles ) ) else: d1 = list( map( lambda p: p.geometry.mean_water_depth( p.get_ts_key(self._timestamp, "Z")), reach1.profiles ) ) d2 = list( map( lambda p: p.geometry.mean_water_depth( p.get_ts_key(self._timestamp, "Z")), reach2.profiles ) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( rk, d, color='orange', lw=1., ) self.lines["mean_depth"] = line if "froude" in self._y: ax = self._axes[unit["froude"]] if self._current_res_id != 2: fr = list( map( lambda p: p.get_ts_key(self._timestamp, "V") / sqrt(9.81 * ( p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")) / p.geometry.wet_width( p.get_ts_key(self._timestamp, "Z")) )), reach.profiles ) ) else: fr1 = list( map( lambda p: p.get_ts_key(self._timestamp, "V") / sqrt(9.81 * ( p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")) / p.geometry.wet_width( p.get_ts_key(self._timestamp, "Z")) )), reach1.profiles ) ) fr2 = list( map( lambda p: p.get_ts_key(self._timestamp, "V") / sqrt(9.81 * ( p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")) / p.geometry.wet_width( p.get_ts_key(self._timestamp, "Z")) )), reach2.profiles ) ) fr = list( map( lambda x, y: x - y, fr1, fr2 ) ) line = ax.plot( rk, fr, color='black', linestyle='--', lw=1., ) self.lines["froude"] = line if "wet_area" in self._y: ax = self._axes[unit["wet_area"]] if self._current_res_id != 2: d = list( map( lambda p: p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")), reach.profiles ) ) else: d1 = list( map( lambda p: p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")), reach1.profiles ) ) d2 = list( map( lambda p: p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")), reach2.profiles ) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( rk, d, color='blue', linestyle='--', lw=1., ) self.lines["wet_area"] = line # Legend lns = reduce( lambda acc, line: acc + line, map(lambda line: self.lines[line], self.lines), [] ) labs = list(map(lambda line: self._trad[line], self.lines)) self.canvas.axes.legend(lns, labs, loc="best") def _redraw_rk(self): results = self.data[self._current_res_id] reach = results.river.reach(self._reach) if self._current_res_id == 2: # compare results reach1 = self.data[0].river.reach(self._reach) reach2 = self.data[1].river.reach(self._reach) rk = reach.geometry.get_rk() z_min = reach.geometry.get_z_min() if reach.has_sediment(): z_min = self.draw_bottom_with_bedload(reach) else: z_min = reach.geometry.get_z_min() q = list( map( lambda p: p.get_ts_key(self._timestamp, "Q"), reach.profiles ) ) z = list( map( lambda p: p.get_ts_key(self._timestamp, "Z"), reach.profiles ) ) v = list( map( lambda p: p.get_ts_key(self._timestamp, "V"), reach.profiles ) ) if "bed_elevation" in self._y: self.lines["bed_elevation"][0].set_ydata(z_min) if "water_elevation" in self._y: self.lines["water_elevation"][0].set_ydata(z) if "bed_elevation" in self._y and self._current_res_id != 2: ax = self._axes[unit["water_elevation"]] self.fill.remove() self.fill = ax.fill_between( rk, z_min, z, color='blue', alpha=0.5, interpolate=True ) if "discharge" in self._y: self.lines["discharge"][0].set_ydata(q) if "velocity" in self._y: self.lines["velocity"][0].set_ydata(v) if "depth" in self._y: if self._current_res_id != 2: d = list( map( lambda p: p.geometry.max_water_depth( p.get_ts_key(self._timestamp, "Z")), reach.profiles ) ) else: d1 = list( map( lambda p: p.geometry.max_water_depth( p.get_ts_key(self._timestamp, "Z")), reach1.profiles ) ) d2 = list( map( lambda p: p.geometry.max_water_depth( p.get_ts_key(self._timestamp, "Z")), reach2.profiles ) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["depth"][0].set_ydata(d) if "mean_depth" in self._y: if self._current_res_id != 2: d = list( map( lambda p: p.geometry.mean_water_depth( p.get_ts_key(self._timestamp, "Z")), reach.profiles ) ) else: d1 = list( map( lambda p: p.geometry.mean_water_depth( p.get_ts_key(self._timestamp, "Z")), reach1.profiles ) ) d2 = list( map( lambda p: p.geometry.mean_water_depth( p.get_ts_key(self._timestamp, "Z")), reach2.profiles ) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["mean_depth"][0].set_ydata(d) if "froude" in self._y: if self._current_res_id != 2: fr = list( map( lambda p: p.get_ts_key(self._timestamp, "V") / sqrt(9.81 * ( p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")) / p.geometry.wet_width( p.get_ts_key(self._timestamp, "Z")) )), reach.profiles ) ) else: fr1 = list( map( lambda p: p.get_ts_key(self._timestamp, "V") / sqrt(9.81 * ( p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")) / p.geometry.wet_width( p.get_ts_key(self._timestamp, "Z")) )), reach1.profiles ) ) fr2 = list( map( lambda p: p.get_ts_key(self._timestamp, "V") / sqrt(9.81 * ( p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")) / p.geometry.wet_width( p.get_ts_key(self._timestamp, "Z")) )), reach2.profiles ) ) fr = list( map( lambda x, y: x - y, fr1, fr2 ) ) self.lines["froude"][0].set_ydata(fr) if "wet_area" in self._y: if self._current_res_id != 2: d = list( map( lambda p: p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")), reach.profiles ) ) else: d1 = list( map( lambda p: p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")), reach1.profiles ) ) d2 = list( map( lambda p: p.geometry.wet_area( p.get_ts_key(self._timestamp, "Z")), reach2.profiles ) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["wet_area"][0].set_ydata(d) 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[self._current_res_id] reach = results.river.reach(self._reach) profile = reach.profile(self._profile) shift = 0 compt = 0 for ax in sorted(self._axes): if compt == 0: self._axes[ax].spines['left'].set_position(('outward', shift)) compt += 1 else: self._axes[ax].spines['right'].set_position(('outward', shift)) shift += 60 ts = self._parent._timestamps if self._current_res_id == 2: # compare results reach1 = self.data[0].river.reach(self._reach) reach2 = self.data[1].river.reach(self._reach) profile1 = reach1.profile(self._profile) profile2 = reach2.profile(self._profile) q1 = profile1.get_key("Q") z1 = profile1.get_key("Z") v1 = profile1.get_key("V") q2 = profile2.get_key("Q") z2 = profile2.get_key("Z") v2 = profile2.get_key("V") q = profile.get_key("Q") z = profile.get_key("Z") v = profile.get_key("V") z_min = profile.geometry.z_min() if reach.has_sediment(): ts_z_min = self.get_ts_zmin(self._profile) else: ts_z_min = list( map( lambda ts: z_min, ts ) ) self.lines = {} if "bed_elevation" in self._y: # Z min is constant in time ax = self._axes[unit["bed_elevation"]] line = ax.plot( ts, ts_z_min, color='grey', lw=1. ) self.lines["bed_elevation"] = line if "water_elevation" in self._y: ax = self._axes[unit["water_elevation"]] line = ax.plot( ts, z, lw=1., color='b', ) self.lines["water_elevation"] = line if "bed_elevation" in self._y and self._current_res_id != 2: self.fill = ax.fill_between( ts, ts_z_min, z, color='blue', alpha=0.5, interpolate=True ) if "discharge" in self._y: ax = self._axes[unit["discharge"]] line = ax.plot( ts, q, lw=1., color='r', ) self.lines["discharge"] = line if "velocity" in self._y: ax = self._axes[unit["velocity"]] line = ax.plot( ts, v, lw=1., color='g', ) self.lines["velocity"] = line if "depth" in self._y: ax = self._axes[unit["depth"]] if self._current_res_id != 2: d = list( map(lambda z: profile.geometry.max_water_depth(z), z) ) else: d1 = list( map(lambda z: profile1.geometry.max_water_depth(z), z1) ) d2 = list( map(lambda z: profile2.geometry.max_water_depth(z), z2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( ts, d, color='brown', lw=1., ) self.lines["depth"] = line if "mean_depth" in self._y: ax = self._axes[unit["mean_depth"]] if self._current_res_id != 2: d = list( map(lambda z: profile.geometry.mean_water_depth(z), z) ) else: d1 = list( map(lambda z: profile1.geometry.mean_water_depth(z), z1) ) d2 = list( map(lambda z: profile2.geometry.mean_water_depth(z), z2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( ts, d, color='orange', lw=1., ) self.lines["mean_depth"] = line if "froude" in self._y: ax = self._axes[unit["froude"]] if self._current_res_id != 2: d = list( map(lambda z, v: v / sqrt(9.81 * ( profile.geometry.wet_area(z) / profile.geometry.wet_width(z)) ), z, v) ) else: d1 = list( map(lambda z, v: v / sqrt(9.81 * ( profile.geometry.wet_area(z) / profile.geometry.wet_width(z)) ), z1, v1) ) d2 = list( map(lambda z, v: v / sqrt(9.81 * ( profile.geometry.wet_area(z) / profile.geometry.wet_width(z)) ), z2, v2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( ts, d, color='black', linestyle='--', lw=1., ) self.lines["froude"] = line if "wet_area" in self._y: ax = self._axes[unit["wet_area"]] if self._current_res_id != 2: d = list( map(lambda z: profile.geometry.wet_area(z), z) ) else: d1 = list( map(lambda z: profile.geometry.wet_area(z), z1) ) d2 = list( map(lambda z: profile.geometry.wet_area(z), z2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) line = ax.plot( ts, d, color='blue', linestyle='--', lw=1., ) self.lines["wet_area"] = line self._customize_x_axes_time(ts) # Legend lns = reduce( lambda acc, line: acc + line, map(lambda line: self.lines[line], self.lines), [] ) labs = list(map(lambda line: self._trad[line], self.lines)) self.canvas.axes.legend(lns, labs, loc="best") def _redraw_time(self): results = self.data[self._current_res_id] reach = results.river.reach(self._reach) profile = reach.profile(self._profile) ts = list(results.get("timestamps")) ts.sort() if self._current_res_id == 2: # compare results reach1 = self.data[0].river.reach(self._reach) reach2 = self.data[1].river.reach(self._reach) profile1 = reach1.profile(self._profile) profile2 = reach2.profile(self._profile) q1 = profile1.get_key("Q") z1 = profile1.get_key("Z") v1 = profile1.get_key("V") q2 = profile2.get_key("Q") z2 = profile2.get_key("Z") v2 = profile2.get_key("V") q = profile.get_key("Q") z = profile.get_key("Z") v = profile.get_key("V") if reach.has_sediment(): ts_z_min = self.get_ts_zmin(self._profile) else: z_min = profile.geometry.z_min() ts_z_min = list( map( lambda ts: z_min, ts ) ) if "bed_elevation" in self._y: self.lines["bed_elevation"][0].set_ydata(ts_z_min) if "water_elevation" in self._y: self.lines["water_elevation"][0].set_ydata(z) if "bed_elevation" in self._y and self._current_res_id != 2: ax = self._axes[unit["bed_elevation"]] self.fill.remove() self.fill = ax.fill_between( ts, ts_z_min, z, color='blue', alpha=0.5, interpolate=True ) if "discharge" in self._y: self.lines["discharge"][0].set_ydata(q) if "velocity" in self._y: self.lines["velocity"][0].set_ydata(v) if "depth" in self._y: if self._current_res_id != 2: d = list( map(lambda z: profile.geometry.max_water_depth(z), z) ) else: d1 = list( map(lambda z: profile1.geometry.max_water_depth(z), z1) ) d2 = list( map(lambda z: profile2.geometry.max_water_depth(z), z2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["depth"][0].set_ydata(d) if "mean_depth" in self._y: if self._current_res_id != 2: d = list( map(lambda z: profile.geometry.mean_water_depth(z), z) ) else: d1 = list( map(lambda z: profile1.geometry.mean_water_depth(z), z1) ) d2 = list( map(lambda z: profile2.geometry.mean_water_depth(z), z2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["mean_depth"][0].set_ydata(d) if "froude" in self._y: if self._current_res_id != 2: d = list( map(lambda z, v: v / sqrt(9.81 * ( profile.geometry.wet_area(z) / profile.geometry.wet_width(z)) ), z, v) ) else: d1 = list( map(lambda z, v: v / sqrt(9.81 * ( profile.geometry.wet_area(z) / profile.geometry.wet_width(z)) ), z1, v1) ) d2 = list( map(lambda z, v: v / sqrt(9.81 * ( profile.geometry.wet_area(z) / profile.geometry.wet_width(z)) ), z2, v2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["froude"][0].set_ydata(d) if "wet_area" in self._y: if self._current_res_id != 2: d = list( map(lambda z: profile.geometry.wet_area(z), z) ) else: d1 = list( map(lambda z: profile.geometry.wet_area(z), z1) ) d2 = list( map(lambda z: profile.geometry.wet_area(z), z2) ) d = list( map( lambda x, y: x - y, d1, d2 ) ) self.lines["wet_area"][0].set_ydata(d) self.canvas.axes.relim(visible_only=True) self.canvas.axes.autoscale_view() def draw(self): self.draw_static() def draw_update(self): if self._x == "rk": self._redraw_rk() elif self._x == "time": self._redraw_time() @timer def draw_static(self): self.canvas.axes.cla() self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) if self.data is None: return self._y_axes = sorted( set( map( lambda y: unit[y], self._y ) ) ) self.canvas.axes.set_xlabel( self._trad[self._x], color='black', fontsize=10 ) if self._current_res_id != 2: self.canvas.axes.set_ylabel( self._trad[self._y_axes[0]], color='black', fontsize=10 ) else: self.canvas.axes.set_ylabel( "Δ " + self._trad[self._y_axes[0]], color='black', fontsize=10 ) self._axes[self._y_axes[0]] = self.canvas.axes if len(self.lines) != 0: self.lines.clear() for axes in self._y_axes[1:]: print("axes: ", axes) if axes in self._axes.keys(): for l in self._axes[axes].lines: l.remove() else: ax_new = self.canvas.axes.twinx() self._axes[axes] = ax_new if self._current_res_id != 2: self._axes[axes].set_ylabel( self._trad[axes], color='black', fontsize=10 ) else: self._axes[axes].set_ylabel( "Δ " + self._trad[axes], color='black', fontsize=10 if self._x == "rk": self._draw_rk() elif self._x == "time": self._draw_time() if self._x == "rk": reach = self.data[self._current_res_id].river.reach(self._reach) profile = reach.profile(self._profile) x = profile.rk elif self._x == "time": x = self._timestamp self._current, = self.canvas.axes.plot( [x, x], self.canvas.axes.get_ylim(), # label=self.label_timestamp, color='grey', linestyle="dashed", lw=1., ) if self.toolbar is not None: self.toolbar.update() self.canvas.draw_idle() @timer def update(self): self.draw_update() self.draw_current() # self.draw_static() 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 != "rk": self.update() else: self.draw_current() def set_result(self, res_id): self._current_res_id = res_id self.draw() def set_timestamp(self, timestamp): self._timestamp = timestamp if self._x != "time": self.update() else: self.draw_current() def draw_current(self): if self._x == "rk": reach = self.data[self._current_res_id].river.reach(self._reach) profile = reach.profile(self._profile) x = profile.rk elif self._x == "time": x = self._timestamp self._current.set_data([x, x], self.canvas.axes.get_ylim()) self.canvas.draw_idle()