Compare commits

..
12 Commits
Author SHA1 Message Date
Dylan Jeannin 797de09683 InitialConditions: sort rows after each generation (single undo step), and fix undo of generation and sort (avoid STOP7 error on Hogneau example) 2026-10-26 16:55:01 +01:00
Dylan Jeannin ef10588880 BoundaryCondition: refit the edit plot to the data after each change 2026-10-26 16:06:55 +01:00
Dylan Jeannin c2a8e17bf3 HydraulicStructures: always show the reach plot, highlight the selected structure in blue, full zoom toolbars and fitted views 2026-10-26 15:52:46 +01:00
Dylan Jeannin a4eee962f7 Geometry: fix error on the first right click in the profile plot (water limits not yet cached) 2026-10-26 10:57:29 +01:00
Dylan Jeannin d8d1b4cd1f HydraulicStructures: fix crash when selecting a rk before the reach 2026-10-23 13:37:03 +02:00
Dylan Jeannin cdeca8a2e8 BoundaryCondition: restore back/forward and view buttons in the edit plot toolbar 2026-10-23 13:23:34 +02:00
Theophile Terraz bddaad0193 debug mesher 2026-09-23 09:28:42 +02:00
Dylan Jeannin 49eb28056e Mage: fix missing $ markers in VAR rules and separate exported check valve entries 2026-09-18 03:10:21 +02:00
Dylan Jeannin 5fb36e7fbe BoundaryConditions: fix index error in deletion for boundary cond. 2026-09-11 16:51:37 +02:00
Dylan Jeannin 71914fdf57 Merge branch 'master' of https://gitlab.com/pamhyr/pamhyr2 2026-09-06 23:15:24 +02:00
Dylan Jeannin 2d7409debb Export csv results: fix export flowrate as a function of time, on a study without sediments transport 2026-09-04 16:45:59 +02:00
parouby 92fb653676 Geometry: Point: Try to create index at each update. 2026-09-04 11:30:30 +02:00
15 changed files with 268 additions and 130 deletions

No files matched your search

+97 -61
View File
@@ -171,8 +171,8 @@ class InternalMeshing(AMeshingTool):
ltot1 = 0.0 ltot1 = 0.0
ltot2 = 0.0 ltot2 = 0.0
alpha = [] alpha = [0.0]
beta = [] beta = [0.0]
# remove names # remove names
sect2.points[start2].name = '' sect2.points[start2].name = ''
sect2.points[end2].name = '' sect2.points[end2].name = ''
@@ -195,67 +195,38 @@ class InternalMeshing(AMeshingTool):
else: # regular case else: # regular case
alpha = list(map(lambda x: x/ltot1, alpha)) # target ratios alpha = list(map(lambda x: x/ltot1, alpha)) # target ratios
beta = list(map(lambda x: x/ltot2, beta)) # current ratios beta = list(map(lambda x: x/ltot2, beta)) # current ratios
for i in range(len1 - len2): match = self._match_indices(alpha, beta)
beta.append(1.0)
beta.append(0.0) # beta[-1]
# loop on the points to insert
for k in range(len1-len2):
trouve = False
for j0 in range(len2):
if trouve:
break
undeplus = True
for j1 in range(j0, len2):
if undeplus:
if beta[j1] <= alpha[j1]:
undeplus = False
break
if undeplus:
if j0 == len2:
trouve = True
else:
j1 = j0+1
if beta[j0]-alpha[j0] > alpha[j1]-beta[j0]:
trouve = True
if trouve: insertions_per_segment = [] # liste de (index, [points])
len2 += 1 for j in range(len2):
for i in reversed(range(j0, len2)): i_start = match[j]
beta[i+1] = beta[i] i_end = match[j + 1]
if (beta[j0] == beta[j0-1]): q_start = sect2.point(start2 + j)
# rien q_end = sect2.point(start2 + j + 1)
pass
else: new_points = []
ratio = (alpha[j0] - beta[j0-1]) \ if i_end - i_start > 1:
/ (beta[j0] - beta[j0-1]) u_start, u_end = alpha[i_start], alpha[i_end]
if ratio < 0.0: span = u_end - u_start
logger.warning(f"ratio négatif {ratio}") for k in range(i_start + 1, i_end):
# on double le point a gauche ratio = (alpha[k] - u_start) / span # dans [0,1]
p = sect2.point(start2+j0-1).copy() p = q_start.copy()
sect2.insert_point(start2+j0-1, p) p.name = ''
sect2.point(start2+j0-1).name = '' p.x = (1.0-ratio) * q_start.x + ratio * q_end.x
beta[j0] = beta[j0-1] p.y = (1.0-ratio) * q_start.y + ratio * q_end.y
else: p.z = (1.0-ratio) * q_start.z + ratio * q_end.z
p = sect2.point(start2+j0).copy() new_points.append(p)
sect2.insert_point(start2+j0, p)
sect2.point(start2+j0+1).name = '' # à insérer après l'indice j
sect2.point(start2+j0+1).x = \ insertions_per_segment.append((j, new_points))
(1.0-ratio) * sect2.point(start2+j0).x + \
ratio * sect2.point(start2+j0+2).x # Insertion en ordre décroissant de j
sect2.point(start2+j0+1).y = \ # pour ne pas perturber les indices
(1.0-ratio) * sect2.point(start2+j0).y + \ for j, new_points in reversed(insertions_per_segment):
ratio * sect2.point(start2+j0+2).y for offset, p in enumerate(new_points):
sect2.point(start2+j0+1).z = \ sect2.insert_point(start2 + j + 1 + offset, p)
(1.0-ratio) * sect2.point(start2+j0).z + \ len2 += 1
ratio * sect2.point(start2+j0+2).z
beta[j0] = (1.-ratio)*beta[j0-1] \
+ ratio*beta[j0+1]
if len1 > len2:
for i in range(len1 - len2):
p = sect2.point(start2+len2).copy()
sect2.insert_point(start2+len2, p)
sect2.point(start2+len2).name = ''
if tag1 != "un": if tag1 != "un":
sect2.point(start2).name = tag1 sect2.point(start2).name = tag1
if tag2 != "np": if tag2 != "np":
@@ -263,6 +234,71 @@ class InternalMeshing(AMeshingTool):
sect2.modified() sect2.modified()
def _match_indices(self, u_ref, v_target):
# appariement optimal (ordre croissant) par programmation dynamique
"""
Trouve, pour chaque v_target[j], un indice i_j dans u_ref tel que
i_0 < i_1 < ... < i_{m-1} et
Sum |u_ref[i_j] - v_target[j]| soit minimal.
Retourne la liste des indices i_j (longueur m),
avec i_0 = 0 et i_{m-1} = n-1 imposés
(les extrémités se correspondent forcément).
"""
n = len(u_ref)
m = len(v_target)
# Les extrémités sont fixées.
fixed_first, fixed_last = 0, n - 1
# DP sur les indices disponibles entre fixed_first+1 et fixed_last-1
# dp[j][i] = coût minimal pour apparier v_target[1..j] aux indices
# se terminant à l'indice i (i croissant strict), j de 1 à m-2.
if m == 2:
return [fixed_first, fixed_last]
# indices internes possibles
candidates = list(range(fixed_first + 1, fixed_last))
inner_targets = v_target[1:-1] # cibles internes (j = 1..m-2)
INF = float("inf")
# dp[j] : dict indice_candidat -> (coût_min, provenance)
dp = [{} for _ in range(len(inner_targets))]
for j, vt in enumerate(inner_targets):
for idx_pos, i in enumerate(candidates):
cost_here = abs(u_ref[i] - vt)
if j == 0:
# doit être > fixed_first
dp[j][i] = (cost_here, fixed_first)
else:
best = (INF, None)
for i_prev in candidates[:idx_pos]:
if i_prev in dp[j - 1]:
c = dp[j - 1][i_prev][0] + cost_here
if c < best[0]:
best = (c, i_prev)
if best[1] is not None:
dp[j][i] = best
# Reconstruction : on part du dernier niveau, on choisit le
# meilleur indice tel que la suite jusqu'à fixed_last
# reste croissante et valide.
last_level = dp[-1]
valid = {i: c for i, c in last_level.items() if i < fixed_last}
if not valid:
raise RuntimeError("Alignement impossible avec ces données.")
best_i = min(valid, key=lambda i: valid[i][0])
chain = [best_i]
for j in range(len(inner_targets) - 1, 0, -1):
prev_i = dp[j][chain[-1]][1]
chain.append(prev_i)
chain.reverse()
return [fixed_first] + chain + [fixed_last]
def update_rk(self, reach, begin_rk, end_rk, def update_rk(self, reach, begin_rk, end_rk,
step: float = 50, step: float = 50,
limites=[-1, -1], limites=[-1, -1],
+5 -6
View File
@@ -95,12 +95,11 @@ class PointXYZ(Point):
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE" "ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
) )
if major == "0" and minor == "2": # Try to create index at each update
if int(release) < 5: execute(
execute( "CREATE INDEX IF NOT EXISTS idx_point " +
"CREATE INDEX idx_point " + "ON geometry_pointXYZ(profile, scenario);"
"ON geometry_pointXYZ(profile, scenario);" )
)
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)
+6 -1
View File
@@ -17,6 +17,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import queue import queue
import types
import random import random
import logging import logging
import numpy as np import numpy as np
@@ -806,7 +807,11 @@ class ProfileXYZ(Profile, SQLSubModel):
return poly return poly
def wet_points(self, z): def wet_points(self, z):
left, right = self.get_water_limits(z) limits = self.get_water_limits(z)
if isinstance(limits, types.GeneratorType):
limits = next(limits)
left, right = limits
points = list(filter(lambda p: p.z < z, self._points)) points = list(filter(lambda p: p.z < z, self._points))
points = [left] + points + [right] points = [left] + points + [right]
+4
View File
@@ -158,11 +158,15 @@ class CommandLineSolver(AbstractSolver):
txt = add_file.text txt = add_file.text
txt = txt.replace("@version", get_version()) txt = txt.replace("@version", get_version())
txt = txt.replace("@date", datetime.now().isoformat(sep=" ")) txt = txt.replace("@date", datetime.now().isoformat(sep=" "))
txt = self._prepare_additional_file_text(add_file.path, txt)
f.write(txt) f.write(txt)
return files return files
def _prepare_additional_file_text(self, path, text):
return text
def export_study_description(self, study, repertory, qlog, name="0"): def export_study_description(self, study, repertory, qlog, name="0"):
files = [] files = []
+20 -1
View File
@@ -679,6 +679,23 @@ class Mage(CommandLineSolver):
return res return res
def _prepare_additional_file_text(self, path, text):
if os.path.splitext(path)[1].lower() != ".var":
return text
lines = []
for line in text.splitlines(keepends=True):
stripped = line.lstrip()
fields = stripped.split()
if stripped.startswith("$"):
# MAGE only recognizes rule markers in the first column.
line = stripped
elif (not stripped.startswith("*") and len(fields) >= 2
and fields[1] == "W2Z"):
line = "$ " + stripped
lines.append(line)
return "".join(lines)
def _export_VAR(self, study, repertory, qlog, name="0"): def _export_VAR(self, study, repertory, qlog, name="0"):
files = [] files = []
@@ -729,9 +746,11 @@ class Mage(CommandLineSolver):
name = bhs.name name = bhs.name
if name == "": if name == "":
name = f"HS_{bhs.id:>3}".replace(" ", "0") name = f"HS_{bhs.id:>3}".replace(" ", "0")
else:
name = name.replace(" ", "_")
f.write( f.write(
f"${name} clapet" f"${name} clapet\n"
) )
return files return files
+1 -1
View File
@@ -54,7 +54,7 @@ class Plot(PamhyrPlot):
self._isometric_axis = False self._isometric_axis = False
self._auto_relim_update = True self._auto_relim_update = True
self._autoscale_update = False self._autoscale_update = True
def custom_ticks(self): def custom_ticks(self):
if self.data.header[0] != "time": if self.data.header[0] != "time":
+4 -1
View File
@@ -185,7 +185,10 @@ class EditBoundaryConditionWindow(PamhyrWindow):
self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas") self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar( self.toolbar = PamhyrPlotToolbar(
self.canvas, self self.canvas, self, items=[
"home", "move", "zoom", "save",
"iso", "back/forward"
]
) )
self.verticalLayout.addWidget(self.toolbar) self.verticalLayout.addWidget(self.toolbar)
self.verticalLayout.addWidget(self.canvas) self.verticalLayout.addWidget(self.canvas)
+1 -1
View File
@@ -124,7 +124,7 @@ class DelCommand(QUndoCommand):
self._bcs.insert(self._tab, row, el) self._bcs.insert(self._tab, row, el)
def redo(self): def redo(self):
self._bcs.delete_i(self._tab, self._rows) self._bcs.delete(self._tab, [el for _, el in self._bc])
class SortCommand(QUndoCommand): class SortCommand(QUndoCommand):
+1 -1
View File
@@ -42,7 +42,7 @@ class PlotAC(PamhyrPlot):
self._isometric_axis = False self._isometric_axis = False
self._auto_relim_update = True self._auto_relim_update = True
self._autoscale_update = False self._autoscale_update = True
@property @property
def river(self): def river(self):
+36 -9
View File
@@ -30,6 +30,14 @@ _translate = QCoreApplication.translate
class PlotRKC(PamhyrPlot): class PlotRKC(PamhyrPlot):
# Class attributes: PlotRKZ (frictions) does not call this __init__
_selected = None # Selected hydraulic structure, in blue
profile = None
line_rk_zmin = None
line_rk_zmin_zmax = None
hs_vlines = None
_hs_drawn = [] # Structures of hs_vlines, in order
def __init__(self, canvas=None, trad=None, toolbar=None, def __init__(self, canvas=None, trad=None, toolbar=None,
river=None, reach=None, profile=None, river=None, reach=None, profile=None,
parent=None): parent=None):
@@ -133,19 +141,14 @@ class PlotRKC(PamhyrPlot):
vymin = [] vymin = []
vymax = [] vymax = []
self.anotate_lst = [] self.anotate_lst = []
self._hs_drawn = []
hs_color = [] hs_color = []
index = self.parent.tableView.selectedIndexes() for hs in lhs:
for i, hs in enumerate(lhs):
section = hs.input_section section = hs.input_section
if section is None: if section is None:
continue continue
if i == index[0].row(): color = self._hs_color(hs)
color = "blue"
elif hs.enabled:
color = "red"
else:
color = "darkgrey"
x = section.rk x = section.rk
if x is not None: if x is not None:
@@ -163,6 +166,7 @@ class PlotRKC(PamhyrPlot):
vymin.append(min(z_min)) vymin.append(min(z_min))
vymax.append(max(z_max)) vymax.append(max(z_max))
hs_color.append(color) hs_color.append(color)
self._hs_drawn.append(hs)
self.hs_vlines = self.canvas.axes.vlines( self.hs_vlines = self.canvas.axes.vlines(
x=vx, ymin=vymin, ymax=vymax, x=vx, ymin=vymin, ymax=vymax,
@@ -171,6 +175,28 @@ class PlotRKC(PamhyrPlot):
color=hs_color, color=hs_color,
) )
def _hs_color(self, hs):
if hs is self._selected:
return "blue"
if hs.enabled:
return "red"
return "darkgrey"
def set_selected(self, hs):
"""Draw the selected structure in blue, without redrawing the
plot (the view is kept)"""
self._selected = hs
if self.hs_vlines is None:
return
colors = [self._hs_color(h) for h in self._hs_drawn]
if colors:
self.hs_vlines.set_color(colors)
for annotation, color in zip(self.anotate_lst, colors):
annotation.set_color(color)
self.canvas.figure.canvas.draw_idle()
def color_highlight(self, highlight): def color_highlight(self, highlight):
reach = self._current_reach reach = self._current_reach
@@ -254,7 +280,8 @@ class PlotRKC(PamhyrPlot):
closest = self._closest_profile(event) closest = self._closest_profile(event)
index = self.parent.tableView.selectedIndexes() index = self.parent.tableView.selectedIndexes()
if self.parent._table is not None: # Moves the selected structure: nothing to do without selection
if self.parent._table is not None and len(index) > 2:
self.parent._table.setData(index[2], closest) self.parent._table.setData(index[2], closest)
return return
+2 -1
View File
@@ -96,7 +96,8 @@ class ComboBoxDelegate(QItemDelegate):
reach = self._data.hydraulic_structures\ reach = self._data.hydraulic_structures\
.get(index.row())\ .get(index.row())\
.input_reach .input_reach
profiles = list( # No reach selected yet: no profile to choose from
profiles = [] if reach is None else list(
filter( filter(
lambda p: p.display_name() == text, lambda p: p.display_name() == text,
reach.reach.profiles reach.reach.profiles
+62 -39
View File
@@ -130,11 +130,13 @@ class HydraulicStructuresWindow(PamhyrWindow):
self._checkbox = self.find(QCheckBox, f"checkBox") self._checkbox = self.find(QCheckBox, f"checkBox")
self._set_checkbox_state() self._set_checkbox_state()
_toolbar_items = ["home", "move", "zoom", "save", "iso", "back/forward"]
def setup_plots(self): def setup_plots(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100) self.canvas = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas") self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar( self.toolbar = PamhyrPlotToolbar(
self.canvas, self self.canvas, self, items=self._toolbar_items
) )
self.plot_layout = self.find(QVBoxLayout, "verticalLayout") self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
self.plot_layout.addWidget(self.toolbar) self.plot_layout.addWidget(self.toolbar)
@@ -143,7 +145,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
self.plot_rkc = PlotRKC( self.plot_rkc = PlotRKC(
canvas=self.canvas, canvas=self.canvas,
river=self._study.river, river=self._study.river,
reach=None, reach=self._displayed_reach(None),
profile=None, profile=None,
trad=self._trad, trad=self._trad,
toolbar=self.toolbar, toolbar=self.toolbar,
@@ -154,7 +156,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
self.canvas_2 = MplCanvas(width=5, height=4, dpi=100) self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
self.canvas_2.setObjectName("canvas_2") self.canvas_2.setObjectName("canvas_2")
self.toolbar_2 = PamhyrPlotToolbar( self.toolbar_2 = PamhyrPlotToolbar(
self.canvas_2, self self.canvas_2, self, items=self._toolbar_items
) )
self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2") self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2")
self.plot_layout_2.addWidget(self.toolbar_2) self.plot_layout_2.addWidget(self.toolbar_2)
@@ -183,7 +185,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
table = self.find(QTableView, "tableView") table = self.find(QTableView, "tableView")
table.selectionModel()\ table.selectionModel()\
.selectionChanged\ .selectionChanged\
.connect(self.update) .connect(self.update_selection)
self._table.dataChanged.connect(self.update) self._table.dataChanged.connect(self.update)
self._table.layoutChanged.connect(self.update) self._table.layoutChanged.connect(self.update)
@@ -282,44 +284,65 @@ class HydraulicStructuresWindow(PamhyrWindow):
) )
def update(self): def update(self):
"""Data changed: plots redrawn, fitted to their data"""
self._set_checkbox_state() self._set_checkbox_state()
self._update_clear_plot() self._update_plots(redraw=True)
def _update_clear_plot(self): def update_selection(self):
"""Selection changed: the selected structure is drawn in blue,
the view is kept (unless its reach is another one)"""
self._set_checkbox_state()
self._update_plots(redraw=False)
def _selected_structure(self):
rows = self.index_selected_rows() rows = self.index_selected_rows()
if len(rows) == 0 or len(self._hs_lst) == 0: if len(rows) == 0 or len(self._hs_lst) == 0:
self._update_clear_all() return None
return self._hs_lst.get(rows[0])
def _displayed_reach(self, selected):
"""Reach of the selected structure; otherwise the reach already
shown, the reach of the first structure, or the first reach"""
edges = self._study.river.enable_edges()
if selected is not None and selected.input_reach in edges:
return selected.input_reach
current = getattr(self, "plot_rkc", None)
if current is not None and current._current_reach in edges:
return current._current_reach
for hs in self._hs_lst.lst:
if hs.input_reach in edges:
return hs.input_reach
return edges[0] if len(edges) > 0 else None
def _update_plots(self, redraw=True):
selected = self._selected_structure()
reach = self._displayed_reach(selected)
self.plot_rkc._selected = selected
if redraw or reach is not self.plot_rkc._current_reach:
self.plot_rkc.set_reach(reach)
else:
self.plot_rkc.set_selected(selected)
self._update_profile_plot(selected, reach)
def _update_profile_plot(self, selected, reach):
profile = None
if (selected is not None and reach is not None
and selected.input_section is not None):
profiles = reach.reach.get_profiles_from_rk(
float(selected.input_section.rk)
)
if profiles:
profile = profiles[0]
if profile is None:
self.plot_ac.clear()
self.plot_ac.update_idle()
return return
reach = self._hs_lst.get(rows[0]).input_reach self.plot_ac.set_reach(reach)
if reach is not None: self.plot_ac.set_profile(profile)
self.plot_rkc.set_reach(reach)
self.plot_ac.set_reach(reach)
profile = self._hs_lst.get(rows[0]).input_section
if profile is not None:
profiles = reach.reach\
.get_profiles_from_rk(
float(profile.rk)
)
if len(profiles) != 0 and profiles is not None:
profile = profiles[0]
self.plot_rkc.set_profile(profile)
self.plot_ac.set_profile(profile)
else:
self._update_clear_profile()
else:
self._update_clear_profile()
else:
self._update_clear_all()
def _update_clear_all(self):
self.plot_rkc.clear()
self.plot_ac.clear()
def _update_clear_profile(self):
self.plot_ac.clear()
self.plot_rkc.clear_profile()
+10
View File
@@ -376,9 +376,19 @@ class InitialConditionTableModel(PamhyrTableModel):
self.layoutChanged.emit() self.layoutChanged.emit()
def generate(self, generator, param, option): def generate(self, generator, param, option):
self.layoutAboutToBeChanged.emit()
self._undo.beginMacro(f"generate {generator}")
self._undo.push( self._undo.push(
GenerateCommand( GenerateCommand(
self._lst, generator, param, option self._lst, generator, param, option
) )
) )
self._undo.push(
SortCommand(
self._lst, False
)
)
self._undo.endMacro()
self.layoutChanged.emit() self.layoutChanged.emit()
+17 -5
View File
@@ -100,15 +100,19 @@ class SortCommand(QUndoCommand):
self._indexes = None self._indexes = None
def undo(self): def undo(self):
ll = self._ics.data order = {
id(x): self._indexes[i]
for i, x in enumerate(self._ics.data)
}
self._ics.sort( self._ics.sort(
key=lambda x: self._indexes[ll.index(x)] key=lambda x: order.get(id(x), len(order))
) )
def redo(self): def redo(self):
self._ics.sort( self._ics.sort(
reverse=self._reverse, reverse=self._reverse,
key=lambda x: x["rk"].rk key=lambda x: ((x["rk"] is None),
0.0 if x["rk"] is None else x["rk"].rk)
) )
if self._indexes is None: if self._indexes is None:
self._indexes = list( self._indexes = list(
@@ -182,11 +186,19 @@ class GenerateCommand(QUndoCommand):
self._ics = ics self._ics = ics
self._param = param self._param = param
self._option = option self._option = option
self._copy = self._ics.data # All the rows, with their deleted flag: the generation marks the
# previous rows as deleted (clear_data)
self._copy = list(self._ics._data)
self._deleted = [d.is_deleted() for d in self._copy]
self._generator = generator self._generator = generator
def undo(self): def undo(self):
self._ics.data = self._copy for data, deleted in zip(self._copy, self._deleted):
if deleted:
data.set_as_deleted()
else:
data.set_as_not_deleted()
self._ics.data = list(self._copy)
def redo(self): def redo(self):
if self._generator == "growing": if self._generator == "growing":
+2 -3
View File
@@ -1150,7 +1150,6 @@ class ResultsWindow(PamhyrWindow):
z = table["Z"][:, profile.global_index] z = table["Z"][:, profile.global_index]
q = table["Q"][:, profile.global_index] q = table["Q"][:, profile.global_index]
v = table["V"][:, profile.global_index] v = table["V"][:, profile.global_index]
zfd = table["zfd"][:, profile.global_index]
if self._current_results == 2: if self._current_results == 2:
reach1 = self._results[0].river.reach(self._reach) reach1 = self._results[0].river.reach(self._reach)
@@ -1169,8 +1168,8 @@ class ResultsWindow(PamhyrWindow):
v2 = table["V"][:, profile2.global_index] v2 = table["V"][:, profile2.global_index]
if "bed_elevation" in y: if "bed_elevation" in y:
if reach.has_bedload(): if reach.has_bedload() and "zfd" in table:
z_min = zfd z_min = table["zfd"][:, profile.global_index]
else: else:
z_min = [profile.geometry.z_min()] * len(self._timestamps) z_min = [profile.geometry.z_min()] * len(self._timestamps)