Compare commits

...
16 changed files with 559 additions and 81 deletions

No files matched your search

+132 -11
View File
@@ -29,6 +29,7 @@ from numpy.core.multiarray import where
from platformdirs import user_cache_dir from platformdirs import user_cache_dir
from Solver.AdisTS import AdisTS from Solver.AdisTS import AdisTS
from Solver.Mage import Mage8
from tools import logger_exception from tools import logger_exception
from PyQt5 import QtGui from PyQt5 import QtGui
@@ -76,14 +77,18 @@ from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
from View.AdditionalFiles.Window import AddFileListWindow from View.AdditionalFiles.Window import AddFileListWindow
from View.REPLines.Window import REPLineListWindow from View.REPLines.Window import REPLineListWindow
from View.SolverParameters.Window import SolverParametersWindow from View.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow from View.RunSolver.Window import (
SelectSolverWindow,
SolverLogWindow,
CompareSolversWindow
)
from View.Results.Window import ResultsWindow # , CompareResultsWindow
from View.RunSolver.WindowAdisTS import ( from View.RunSolver.WindowAdisTS import (
SelectSolverWindowAdisTS, SelectSolverWindowAdisTS,
SolverLogWindowAdisTS SolverLogWindowAdisTS
) )
from View.CheckList.Window import CheckListWindow from View.CheckList.Window import CheckListWindow
from View.CheckList.WindowAdisTS import CheckListWindowAdisTS from View.CheckList.WindowAdisTS import CheckListWindowAdisTS
from View.Results.Window import ResultsWindow
from View.Results.WindowAdisTS import ResultsWindowAdisTS from View.Results.WindowAdisTS import ResultsWindowAdisTS
from View.Results.ReadingResultsDialog import ReadingResultsDialog from View.Results.ReadingResultsDialog import ReadingResultsDialog
from View.Debug.Window import ReplWindow from View.Debug.Window import ReplWindow
@@ -92,6 +97,10 @@ from View.Pollutants.Window import PollutantsWindow
from View.D90AdisTS.Window import D90AdisTSWindow from View.D90AdisTS.Window import D90AdisTSWindow
from View.DIFAdisTS.Window import DIFAdisTSWindow from View.DIFAdisTS.Window import DIFAdisTSWindow
from Solver.Solvers import GenericSolver
from Model.Results.Results import Results
# Optional internal display of documentation for make the application # Optional internal display of documentation for make the application
# package lighter... # package lighter...
try: try:
@@ -134,7 +143,7 @@ define_model_action = [
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs", "action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
"action_menu_edit_hydraulic_structures", "action_menu_additional_file", "action_menu_edit_hydraulic_structures", "action_menu_additional_file",
"action_menu_results_last", "action_open_results_from_file", "action_menu_results_last", "action_open_results_from_file",
"action_menu_boundary_conditions_sediment", "action_compare_results", "action_menu_boundary_conditions_sediment",
"action_menu_rep_additional_lines", "action_menu_output_rk", "action_menu_rep_additional_lines", "action_menu_output_rk",
"action_menu_run_adists", "action_menu_pollutants", "action_menu_run_adists", "action_menu_pollutants",
"action_menu_d90", "action_menu_dif", "action_menu_d90", "action_menu_dif",
@@ -279,6 +288,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_close": self.close_model, "action_menu_close": self.close_model,
"action_menu_results_last": self.open_last_results, "action_menu_results_last": self.open_last_results,
"action_open_results_from_file": self.open_results_from_file, "action_open_results_from_file": self.open_results_from_file,
"action_compare_results": self.compare_results,
"action_open_results_adists": self.open_results_adists, "action_open_results_adists": self.open_results_adists,
# Help # Help
"action_menu_pamhyr_users_wiki": self.open_doc_user, "action_menu_pamhyr_users_wiki": self.open_doc_user,
@@ -1427,17 +1437,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
ResultsWindow, ResultsWindow,
data=[ data=[
self._study, self._study,
None, # No config None, # No config
solver, results]
results
]
): ):
return return
res = ResultsWindow( res = ResultsWindow(
study=self._study, study=self._study,
solver=solver, results=[results],
results=results,
parent=self parent=self
) )
res.show() res.show()
@@ -1486,7 +1493,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
self._study, self._study,
None, # No config None, # No config
solver, solver,
results results,
self
] ]
): ):
return return
@@ -1550,10 +1558,123 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
file_name = dialog.selectedFiles() file_name = dialog.selectedFiles()
logger.info(f"Select results: {file_name}") logger.info(f"Select results: {file_name}")
self.open_solver_results( self.open_solver_results(
self._last_solver, Mage8("Mage"),
results=file_name[0] results=file_name[0]
) )
def compare_results(self):
if self._study is None:
return
run = CompareSolversWindow(
study=self._study,
config=self.conf,
parent=self
)
if run.exec():
results = self.diff_results(run.solver1,
run.solver2)
# At least one result not available
if results is None:
return
# Windows already opened
if self.sub_window_exists(
ResultsWindow,
data=[
self._study,
None] + # No config
results
):
#w = self.get_sub_window(
#ResultsWindow,
#data=[
#self._study,
#None, # No config
#results,
#parent=self
#])
#w.add_result(result[1], run.solver2)
return
res = ResultsWindow(
study=self._study,
results=results,
parent=self
)
res.show()
#res = CompareResultsWindow(
#study=self._study,
#solver=results._solver,
#results=results,
#parent=self
#)
#res.show()
def diff_results(self, solver1, solver2):
if solver1 is None:
# TODO message
return None
if solver2 is None:
# TODO message
return None
solver3 = GenericSolver(solver1.name+" - "+solver2.name)
result1 = solver1.results(
self._study,
self._solver_workdir(solver1),
)
if result1 is None:
# TODO message
return None
result2 = solver2.results(
self._study,
self._solver_workdir(solver2),
)
if result2 is None:
# TODO message
return None
if result2.get("nb_reach") != result1.get("nb_reach"):
# TODO message
return None
if result2.get("nb_profile") != result1.get("nb_profile"):
# TODO message
return None
return [result1, result2]
result3 = Results(self._study, solver3)
result3.set("nb_reach", result1.get("nb_reach"))
result3.set("nb_profile", result1.get("nb_profile"))
ts = list(result1.get("timestamps").intersection(result2.get("timestamps")))
result3.set("timestamps", ts)
for i in range(int(result1.get("nb_reach"))):
# Add reach to results reach list
r = result3.river.add(i)
for timestamp in result3.get("timestamps"):
for r in range(int(result1.get("nb_reach"))):
reach1 = result1.river.reach(r)
reach2 = result2.river.reach(r)
reach3 = result3.river.reach(r)
for p, (profile1, profile2) in enumerate(zip(reach1.profiles, reach2.profiles)):
for key in ["Z", "Q"]:
d1 = profile1.get_ts_key(timestamp, key)
d2 = profile2.get_ts_key(timestamp, key)
reach3.set(p, timestamp, key, d1-d2)
return result3
def open_results_adists(self): def open_results_adists(self):
if self._study is None: if self._study is None:
return return
+14 -9
View File
@@ -49,7 +49,7 @@ unit = {
class CustomPlot(PamhyrPlot): class CustomPlot(PamhyrPlot):
def __init__(self, x, y, envelop, reach, profile, timestamp, def __init__(self, x, y, envelop, reach, profile, timestamp,
data=None, canvas=None, trad=None, data=None, canvas=None, trad=None, res_id=0,
toolbar=None, parent=None): toolbar=None, parent=None):
super(CustomPlot, self).__init__( super(CustomPlot, self).__init__(
canvas=canvas, canvas=canvas,
@@ -65,6 +65,7 @@ class CustomPlot(PamhyrPlot):
self._reach = reach self._reach = reach
self._profile = profile self._profile = profile
self._timestamp = timestamp self._timestamp = timestamp
self._current_res_id = res_id
logger.debug( logger.debug(
"Create custom plot for: " + "Create custom plot for: " +
@@ -130,7 +131,7 @@ class CustomPlot(PamhyrPlot):
""" """
Get SL list for profile p at initial time (initial data) Get SL list for profile p at initial time (initial data)
""" """
t0 = min(list(self.data.get("timestamps"))) t0 = min(list(self.data[self._current_res_id].get("timestamps")))
return map( return map(
lambda p: p.get_ts_key(t0, "sl")[0], lambda p: p.get_ts_key(t0, "sl")[0],
reach.profiles reach.profiles
@@ -146,7 +147,7 @@ class CustomPlot(PamhyrPlot):
) )
def get_ts_zmin(self, profile): def get_ts_zmin(self, profile):
results = self.data results = self.data[self._current_res_id]
nt = len(list(results.get("timestamps"))) nt = len(list(results.get("timestamps")))
reach = results.river.reach(self._reach) reach = results.river.reach(self._reach)
berdrock = self.sl_compute_bedrock(reach) berdrock = self.sl_compute_bedrock(reach)
@@ -167,7 +168,7 @@ class CustomPlot(PamhyrPlot):
return ts_z_min return ts_z_min
def _draw_rk(self): def _draw_rk(self):
results = self.data results = self.data[self._current_res_id]
reach = results.river.reach(self._reach) reach = results.river.reach(self._reach)
rk = reach.geometry.get_rk() rk = reach.geometry.get_rk()
if reach.has_sediment(): if reach.has_sediment():
@@ -485,7 +486,7 @@ class CustomPlot(PamhyrPlot):
self.canvas.axes.legend(lns, labs, loc="best") self.canvas.axes.legend(lns, labs, loc="best")
def _redraw_rk(self): def _redraw_rk(self):
results = self.data results = self.data[self._current_res_id]
reach = results.river.reach(self._reach) reach = results.river.reach(self._reach)
rk = reach.geometry.get_rk() rk = reach.geometry.get_rk()
z_min = reach.geometry.get_z_min() z_min = reach.geometry.get_z_min()
@@ -623,7 +624,7 @@ class CustomPlot(PamhyrPlot):
self.canvas.axes.set_xticks(ticks=fx, labels=xt, rotation=45) self.canvas.axes.set_xticks(ticks=fx, labels=xt, rotation=45)
def _draw_time(self): def _draw_time(self):
results = self.data results = self.data[self._current_res_id]
reach = results.river.reach(self._reach) reach = results.river.reach(self._reach)
profile = reach.profile(self._profile) profile = reach.profile(self._profile)
@@ -774,7 +775,7 @@ class CustomPlot(PamhyrPlot):
def _redraw_time(self): def _redraw_time(self):
results = self.data results = self.data[self._current_res_id]
reach = results.river.reach(self._reach) reach = results.river.reach(self._reach)
profile = reach.profile(self._profile) profile = reach.profile(self._profile)
ts = list(results.get("timestamps")) ts = list(results.get("timestamps"))
@@ -895,7 +896,7 @@ class CustomPlot(PamhyrPlot):
elif self._x == "time": elif self._x == "time":
self._draw_time() self._draw_time()
if self._x == "rk": if self._x == "rk":
reach = self.data.river.reach(self._reach) reach = self.data[self._current_res_id].river.reach(self._reach)
profile = reach.profile(self._profile) profile = reach.profile(self._profile)
x = profile.rk x = profile.rk
elif self._x == "time": elif self._x == "time":
@@ -935,6 +936,10 @@ class CustomPlot(PamhyrPlot):
else: else:
self.draw_current() self.draw_current()
def set_result(self, res_id):
self._current_res_id = res_id
self.draw()
def set_timestamp(self, timestamp): def set_timestamp(self, timestamp):
self._timestamp = timestamp self._timestamp = timestamp
@@ -945,7 +950,7 @@ class CustomPlot(PamhyrPlot):
def draw_current(self): def draw_current(self):
if self._x == "rk": if self._x == "rk":
reach = self.data.river.reach(self._reach) reach = self.data[self._current_res_id].river.reach(self._reach)
profile = reach.profile(self._profile) profile = reach.profile(self._profile)
x = profile.rk x = profile.rk
elif self._x == "time": elif self._x == "time":
+15 -6
View File
@@ -29,7 +29,7 @@ _translate = QCoreApplication.translate
class PlotAC(PamhyrPlot): class PlotAC(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None, def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0, res_id=0,
parent=None): parent=None):
super(PlotAC, self).__init__( super(PlotAC, self).__init__(
canvas=canvas, canvas=canvas,
@@ -39,9 +39,10 @@ class PlotAC(PamhyrPlot):
parent=parent parent=parent
) )
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results[res_id].get("timestamps"))
self._current_reach_id = reach_id self._current_reach_id = reach_id
self._current_profile_id = profile_id self._current_profile_id = profile_id
self._current_res_id = res_id
self.label_x = self._trad['x'] self.label_x = self._trad['x']
self.label_y = self._trad["unit_elevation"] self.label_y = self._trad["unit_elevation"]
@@ -62,7 +63,7 @@ class PlotAC(PamhyrPlot):
@results.setter @results.setter
def results(self, results): def results(self, results):
self.data = results self.data = results
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results[self._current_res_id].get("timestamps"))
@timer @timer
def draw(self, highlight=None): def draw(self, highlight=None):
@@ -71,7 +72,11 @@ class PlotAC(PamhyrPlot):
if self.results is None: if self.results is None:
return return
reach = self.results.river.reach(self._current_reach_id) 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) profile = reach.profile(self._current_profile_id)
self.draw_profile(reach, profile) self.draw_profile(reach, profile)
@@ -137,10 +142,14 @@ class PlotAC(PamhyrPlot):
self._current_profile_id = profile_id self._current_profile_id = profile_id
self.update() self.update()
def set_result(self, res_id):
self._current_result_id = res_id
self.update()
def set_timestamp(self, timestamp): def set_timestamp(self, timestamp):
self._current_timestamp = timestamp self._current_timestamp = timestamp
reach = self.results.river.reach(self._current_reach_id) reach = self.results[self._current_res_id].river.reach(self._current_reach_id)
profile = reach.profile(self._current_profile_id) profile = reach.profile(self._current_profile_id)
x = profile.geometry.get_station() x = profile.geometry.get_station()
z = profile.geometry.z() z = profile.geometry.z()
@@ -152,7 +161,7 @@ class PlotAC(PamhyrPlot):
if not self._init: if not self._init:
self.draw() self.draw()
reach = self.results.river.reach(self._current_reach_id) reach = self.results[self._current_res_id].river.reach(self._current_reach_id)
profile = reach.profile(self._current_profile_id) profile = reach.profile(self._current_profile_id)
x = profile.geometry.get_station() x = profile.geometry.get_station()
z = profile.geometry.z() z = profile.geometry.z()
+17 -7
View File
@@ -35,7 +35,7 @@ logger = logging.getLogger()
class PlotH(PamhyrPlot): class PlotH(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None, def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0, res_id=0,
parent=None): parent=None):
super(PlotH, self).__init__( super(PlotH, self).__init__(
canvas=canvas, canvas=canvas,
@@ -47,9 +47,10 @@ class PlotH(PamhyrPlot):
self._mode = "time" self._mode = "time"
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results[res_id].get("timestamps"))
self._current_reach_id = reach_id self._current_reach_id = reach_id
self._current_profile_id = profile_id self._current_profile_id = profile_id
self._current_res_id = res_id
self.label_x = self._trad["unit_time_s"] self.label_x = self._trad["unit_time_s"]
self.label_y = self._trad["unit_discharge"] self.label_y = self._trad["unit_discharge"]
@@ -70,7 +71,7 @@ class PlotH(PamhyrPlot):
@results.setter @results.setter
def results(self, results): def results(self, results):
self.data = results self.data = results
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results[self._current_res_id].get("timestamps"))
@timer @timer
def draw(self, highlight=None): def draw(self, highlight=None):
@@ -79,7 +80,11 @@ class PlotH(PamhyrPlot):
if self.results is None: if self.results is None:
return return
reach = self.results.river.reach(self._current_reach_id) 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) profile = reach.profile(self._current_profile_id)
if reach.geometry.number_profiles == 0: if reach.geometry.number_profiles == 0:
@@ -99,7 +104,7 @@ class PlotH(PamhyrPlot):
self._init = True self._init = True
def draw_data(self, reach, profile): def draw_data(self, reach, profile):
self.ts = list(self.results.get("timestamps")) self.ts = list(self.results[self._current_res_id].get("timestamps"))
self.ts.sort() self.ts.sort()
x = self.ts x = self.ts
@@ -123,7 +128,7 @@ class PlotH(PamhyrPlot):
) )
def draw_max(self, reach): def draw_max(self, reach):
self.ts = list(self.results.get("timestamps")) self.ts = list(self.results[self._current_res_id].get("timestamps"))
self.ts.sort() self.ts.sort()
x = self.ts x = self.ts
@@ -152,6 +157,10 @@ class PlotH(PamhyrPlot):
self._current_profile_id = profile_id self._current_profile_id = profile_id
self.update() self.update()
def set_result(self, res_id):
self._current_result_id = res_id
self.update()
def set_timestamp(self, timestamp): def set_timestamp(self, timestamp):
self._current_timestamp = timestamp self._current_timestamp = timestamp
self.update_current() self.update_current()
@@ -165,7 +174,8 @@ class PlotH(PamhyrPlot):
self.update_idle() self.update_idle()
def update_data(self): def update_data(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
profile = reach.profile(self._current_profile_id) profile = reach.profile(self._current_profile_id)
x = self.ts x = self.ts
+23 -9
View File
@@ -32,7 +32,7 @@ logger = logging.getLogger()
class PlotRKC(PamhyrPlot): class PlotRKC(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None, def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0, res_id=0,
parent=None): parent=None):
super(PlotRKC, self).__init__( super(PlotRKC, self).__init__(
canvas=canvas, canvas=canvas,
@@ -42,10 +42,12 @@ class PlotRKC(PamhyrPlot):
parent=parent parent=parent
) )
self._timestamps = results.get("timestamps") self._timestamps = results[res_id].get("timestamps")
self._current_timestamp = max(results[res_id].get("timestamps"))
self._current_timestamp = max(self._timestamps) self._current_timestamp = max(self._timestamps)
self._current_reach_id = reach_id self._current_reach_id = reach_id
self._current_profile_id = profile_id self._current_profile_id = profile_id
self._current_res_id = res_id
self.label_x = self._trad["unit_rk"] self.label_x = self._trad["unit_rk"]
self.label_y = self._trad["unit_elevation"] self.label_y = self._trad["unit_elevation"]
@@ -63,7 +65,7 @@ class PlotRKC(PamhyrPlot):
@results.setter @results.setter
def results(self, results): def results(self, results):
self.data = results self.data = results
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results[self._current_res_id].get("timestamps"))
@timer @timer
def draw(self, highlight=None): def draw(self, highlight=None):
@@ -72,7 +74,11 @@ class PlotRKC(PamhyrPlot):
if self.results is None: if self.results is None:
return return
reach = self.results.river.reach(self._current_reach_id) 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)
self.draw_bottom(reach) self.draw_bottom(reach)
self.draw_water_elevation(reach) self.draw_water_elevation(reach)
@@ -111,7 +117,7 @@ class PlotRKC(PamhyrPlot):
lambda hs: hs._input_reach.reach is reach.geometry, lambda hs: hs._input_reach.reach is reach.geometry,
filter( filter(
lambda hs: hs._input_reach is not None, lambda hs: hs._input_reach is not None,
self.results.study.river.hydraulic_structures.lst self.results[self._current_res_id].study.river.hydraulic_structures.lst
) )
) )
@@ -312,6 +318,10 @@ class PlotRKC(PamhyrPlot):
self._current_profile_id = profile_id self._current_profile_id = profile_id
self.update_current() self.update_current()
def set_result(self, res_id):
self._current_result_id = res_id
self.update()
def set_timestamp(self, timestamp): def set_timestamp(self, timestamp):
self._current_timestamp = timestamp self._current_timestamp = timestamp
self.update() self.update()
@@ -320,7 +330,8 @@ class PlotRKC(PamhyrPlot):
if not self._init: if not self._init:
self.draw() self.draw()
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
if reach.has_sediment(): if reach.has_sediment():
self.update_bottom_with_bedload() self.update_bottom_with_bedload()
@@ -329,7 +340,8 @@ class PlotRKC(PamhyrPlot):
self.update_idle() self.update_idle()
def update_water_elevation(self): def update_water_elevation(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
rk = reach.geometry.get_rk() rk = reach.geometry.get_rk()
z_min = reach.geometry.get_z_min() z_min = reach.geometry.get_z_min()
@@ -354,7 +366,8 @@ class PlotRKC(PamhyrPlot):
) )
def update_current(self): def update_current(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
rk = reach.geometry.get_rk() rk = reach.geometry.get_rk()
z_min = reach.geometry.get_z_min() z_min = reach.geometry.get_z_min()
z_max = reach.geometry.get_z_max() z_max = reach.geometry.get_z_max()
@@ -367,7 +380,8 @@ class PlotRKC(PamhyrPlot):
self.canvas.figure.canvas.draw_idle() self.canvas.figure.canvas.draw_idle()
def update_bottom_with_bedload(self): def update_bottom_with_bedload(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
rk = reach.geometry.get_rk() rk = reach.geometry.get_rk()
z = self.sl_compute_current_z(reach) z = self.sl_compute_current_z(reach)
+23 -9
View File
@@ -38,7 +38,7 @@ logger = logging.getLogger()
class PlotXY(PamhyrPlot): class PlotXY(PamhyrPlot):
def __init__(self, canvas=None, trad=None, toolbar=None, def __init__(self, canvas=None, trad=None, toolbar=None,
results=None, reach_id=0, profile_id=0, results=None, reach_id=0, profile_id=0, res_id=0,
display_current=True, parent=None): display_current=True, parent=None):
super(PlotXY, self).__init__( super(PlotXY, self).__init__(
canvas=canvas, canvas=canvas,
@@ -52,10 +52,11 @@ class PlotXY(PamhyrPlot):
self.line_gl = [] self.line_gl = []
self.overflow = [] self.overflow = []
self._timestamps = results.get("timestamps") self._timestamps = results[res_id].get("timestamps")
self._current_timestamp = max(self._timestamps) self._current_timestamp = max(self._timestamps)
self._current_reach_id = reach_id self._current_reach_id = reach_id
self._current_profile_id = profile_id self._current_profile_id = profile_id
self._current_res_id = res_id
self.label_x = _translate("Results", "X (m)") self.label_x = _translate("Results", "X (m)")
self.label_y = _translate("Results", "Y (m)") self.label_y = _translate("Results", "Y (m)")
@@ -136,7 +137,7 @@ class PlotXY(PamhyrPlot):
@results.setter @results.setter
def results(self, results): def results(self, results):
self.data = results self.data = results
self._current_timestamp = max(results.get("timestamps")) self._current_timestamp = max(results[self._current_res_id].get("timestamps"))
@timer @timer
def draw(self, highlight=None): def draw(self, highlight=None):
@@ -145,8 +146,12 @@ class PlotXY(PamhyrPlot):
if self.results is None: if self.results is None:
return return
reach = self.results.river.reach(self._current_reach_id) if self.results[self._current_res_id] is None:
reaches = self.results.river.reachs return
results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
reaches = results.river.reachs
self.draw_profiles(reach, reaches) self.draw_profiles(reach, reaches)
self.draw_water_elevation(reach) self.draw_water_elevation(reach)
@@ -272,7 +277,8 @@ class PlotXY(PamhyrPlot):
) )
def draw_water_elevation(self, reach): def draw_water_elevation(self, reach):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], [] poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], []
for profile in reach.profiles: for profile in reach.profiles:
@@ -308,6 +314,11 @@ class PlotXY(PamhyrPlot):
self.update_profile() self.update_profile()
self.update_idle() self.update_idle()
def set_result(self, res_id):
self._current_result_id = res_id
self.update_profile()
self.update_idle()
def set_timestamp(self, timestamp): def set_timestamp(self, timestamp):
self._current_timestamp = timestamp self._current_timestamp = timestamp
self.update() self.update()
@@ -322,7 +333,8 @@ class PlotXY(PamhyrPlot):
self.update_idle() self.update_idle()
def update_profile(self): def update_profile(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
profile = reach.profile(self._current_profile_id) profile = reach.profile(self._current_profile_id)
self.plot_selected.set_data( self.plot_selected.set_data(
@@ -331,7 +343,8 @@ class PlotXY(PamhyrPlot):
) )
def update_water_elevation(self): def update_water_elevation(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], [] poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], []
for profile in reach.profiles: for profile in reach.profiles:
@@ -358,7 +371,8 @@ class PlotXY(PamhyrPlot):
self.water_fill[0].set_xy(poly) self.water_fill[0].set_xy(poly)
def update_water_elevation_overflow(self): def update_water_elevation_overflow(self):
reach = self.results.river.reach(self._current_reach_id) results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id)
profile = reach.profile(self._current_profile_id) profile = reach.profile(self._current_profile_id)
overflow = [] overflow = []
+14 -7
View File
@@ -46,17 +46,15 @@ _translate = QCoreApplication.translate
class TableModel(PamhyrTableModel): class TableModel(PamhyrTableModel):
def _setup_lst(self): def _setup_lst(self):
_river = self._data.river _river = self._data[0].river
print("data: ", self._data)
print("river: ", _river)
print("reaches: ", _river.reachs)
if self._opt_data == "reach": if self._opt_data == "reach":
self._lst = _river.reachs self._lst = _river.reachs
print("optreach: ", self._lst)
elif self._opt_data == "profile": elif self._opt_data == "profile":
self._lst = _river.reach(0).profiles self._lst = _river.reach(0).profiles
elif self._opt_data == "raw_data": elif self._opt_data == "raw_data":
self._lst = _river.reach(0).profiles self._lst = _river.reach(0).profiles
elif self._opt_data == "solver":
self._lst = self._parent._solvers
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._timestamp = 0.0 self._timestamp = 0.0
@@ -80,6 +78,10 @@ class TableModel(PamhyrTableModel):
elif self._headers[column] == "rk": elif self._headers[column] == "rk":
v = self._lst[row].rk v = self._lst[row].rk
return f"{v:.4f}" return f"{v:.4f}"
elif self._opt_data == "solver":
if self._headers[column] == "solver":
v = self._lst[row].name
return str(v)
elif self._opt_data == "raw_data": elif self._opt_data == "raw_data":
p = self._lst[row] p = self._lst[row]
if self._headers[column] == "name": if self._headers[column] == "name":
@@ -127,7 +129,10 @@ class TableModel(PamhyrTableModel):
v = self._lst[row].geometry.speed(q, z) v = self._lst[row].geometry.speed(q, z)
a = self._lst[row].geometry.wet_area(z) a = self._lst[row].geometry.wet_area(z)
b = self._lst[row].geometry.wet_width(z) b = self._lst[row].geometry.wet_width(z)
froude = v / sqrt(9.81 * (a / b)) if b == 0.0 or a == 0.0:
froude = 0.0
else:
froude = v / sqrt(9.81 * (a / b))
return f"{froude:.4f}" return f"{froude:.4f}"
else: else:
v = 0.0 v = 0.0
@@ -136,12 +141,14 @@ class TableModel(PamhyrTableModel):
return QVariant() return QVariant()
def update(self, reach): def update(self, reach):
_river = self._data.river _river = self._data[0].river
if self._opt_data == "reach": if self._opt_data == "reach":
self._lst = _river.reachs self._lst = _river.reachs
elif self._opt_data == "profile" or self._opt_data == "raw_data": elif self._opt_data == "profile" or self._opt_data == "raw_data":
self._lst = _river.reach(reach).profiles self._lst = _river.reach(reach).profiles
elif self._opt_data == "solver":
self._lst = self._parent._solvers
self.layoutChanged.emit() self.layoutChanged.emit()
+1 -1
View File
@@ -45,6 +45,7 @@ _translate = QCoreApplication.translate
class TableModel(PamhyrTableModel): class TableModel(PamhyrTableModel):
def _setup_lst(self): def _setup_lst(self):
_river = self._data.river _river = self._data.river
self._timestamp = min(list(self._data.get("timestamps")))
if self._opt_data == "reach": if self._opt_data == "reach":
self._lst = _river.reachs self._lst = _river.reachs
elif self._opt_data == "profile": elif self._opt_data == "profile":
@@ -57,7 +58,6 @@ class TableModel(PamhyrTableModel):
self._lst = tmp_list self._lst = tmp_list
def __init__(self, type_pol, **kwargs): def __init__(self, type_pol, **kwargs):
self._timestamp = 0.0
self._type_pol = type_pol self._type_pol = type_pol
super(TableModel, self).__init__(**kwargs) super(TableModel, self).__init__(**kwargs)
+100 -14
View File
@@ -61,7 +61,10 @@ from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import (
) )
from View.Results.Table import TableModel from View.Results.Table import TableModel
from View.Results.translate import ResultsTranslate from View.Results.translate import (
ResultsTranslate,
CompareResultsTranslate
)
from View.Stricklers.Window import StricklersWindow from View.Stricklers.Window import StricklersWindow
_translate = QCoreApplication.translate _translate = QCoreApplication.translate
@@ -82,16 +85,17 @@ class ResultsWindow(PamhyrWindow):
) )
def __init__(self, study=None, config=None, def __init__(self, study=None, config=None,
solver=None, results=None, results=None, parent=None, trad=None):
parent=None): self._solvers = [r._solver for r in results]
self._solver = solver
self._results = results self._results = results
self._current_results = 0
trad = ResultsTranslate() if trad is None:
trad = ResultsTranslate()
name = ( name = (
trad[self._pamhyr_name] + " - " trad[self._pamhyr_name] + " - "
+ study.name + " - " + study.name + " - "
+ self._solver.name + " - ".join([s.name for s in self._solvers])
) )
super(ResultsWindow, self).__init__( super(ResultsWindow, self).__init__(
@@ -102,13 +106,13 @@ class ResultsWindow(PamhyrWindow):
parent=parent parent=parent
) )
self._hash_data.append(self._solver) for r in results:
self._hash_data.append(self._results) self._hash_data.append(r)
self._additional_plot = {} self._additional_plot = {}
try: try:
self._timestamps = sorted(list(self._results.get("timestamps"))) self._timestamps = sorted(list(self._results[self._current_results].get("timestamps")))
self.setup_slider() self.setup_slider()
self.setup_table() self.setup_table()
@@ -121,20 +125,24 @@ class ResultsWindow(PamhyrWindow):
def setup_table(self): def setup_table(self):
self._table = {} self._table = {}
for t in ["reach", "profile", "raw_data"]: for t in ["reach", "profile", "raw_data", "solver"]:
table = self.find(QTableView, f"tableView_{t}") table = self.find(QTableView, f"tableView_{t}")
self._table[t] = TableModel( self._table[t] = TableModel(
table_view=table, table_view=table,
table_headers=self._trad.get_dict(f"table_headers_{t}"), table_headers=self._trad.get_dict(f"table_headers_{t}"),
data=self._results, data=self._results,
undo=self._undo_stack, undo=self._undo_stack,
opt_data=t opt_data=t,
parent=self
) )
self._table[t]._timestamp = self._timestamps[ self._table[t]._timestamp = self._timestamps[
self._slider_time.value()] self._slider_time.value()]
if len(self._results) <= 1:
table = self.find(QTableView, f"tableView_solver")
table.hide()
def setup_slider(self): def setup_slider(self):
default_reach = self._results.river.reach(0) default_reach = self._results[self._current_results].river.reach(0)
self._slider_time = self.find(QSlider, f"horizontalSlider_time") self._slider_time = self.find(QSlider, f"horizontalSlider_time")
self._slider_time.setMaximum(len(self._timestamps) - 1) self._slider_time.setMaximum(len(self._timestamps) - 1)
@@ -181,6 +189,7 @@ class ResultsWindow(PamhyrWindow):
results=self._results, results=self._results,
reach_id=0, reach_id=0,
profile_id=0, profile_id=0,
res_id=self._current_results,
trad=self._trad, trad=self._trad,
toolbar=self.toolbar, toolbar=self.toolbar,
display_current=True, display_current=True,
@@ -205,6 +214,7 @@ class ResultsWindow(PamhyrWindow):
results=self._results, results=self._results,
reach_id=0, reach_id=0,
profile_id=0, profile_id=0,
res_id=self._current_results,
trad=self._trad, trad=self._trad,
toolbar=self.toolbar_2 toolbar=self.toolbar_2
) )
@@ -227,6 +237,7 @@ class ResultsWindow(PamhyrWindow):
results=self._results, results=self._results,
reach_id=0, reach_id=0,
profile_id=0, profile_id=0,
res_id=self._current_results,
trad=self._trad, trad=self._trad,
toolbar=self.toolbar_3 toolbar=self.toolbar_3
) )
@@ -250,6 +261,7 @@ class ResultsWindow(PamhyrWindow):
results=self._results, results=self._results,
reach_id=0, reach_id=0,
profile_id=0, profile_id=0,
res_id=self._current_results,
trad=self._trad, trad=self._trad,
toolbar=self.toolbar_4 toolbar=self.toolbar_4
) )
@@ -324,9 +336,10 @@ class ResultsWindow(PamhyrWindow):
"reach": self._set_current_reach, "reach": self._set_current_reach,
"profile": self._set_current_profile, "profile": self._set_current_profile,
"raw_data": self._set_current_profile_raw_data, "raw_data": self._set_current_profile_raw_data,
"solver": self._set_current_results,
} }
for t in ["reach", "profile", "raw_data"]: for t in ["reach", "profile", "raw_data", "solver"]:
table = self.find(QTableView, f"tableView_{t}") table = self.find(QTableView, f"tableView_{t}")
table.selectionModel()\ table.selectionModel()\
@@ -374,7 +387,28 @@ class ResultsWindow(PamhyrWindow):
) )
table.scrollTo(index) table.scrollTo(index)
def update(self, reach_id=None, profile_id=None, timestamp=None): def update_table_selection_solver(self, ind):
table = self.find(QTableView, f"tableView_solver")
selectionModel = table.selectionModel()
index = table.model().index(ind, 0)
selectionModel.select(
index,
QItemSelectionModel.Rows |
QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Select
)
table.scrollTo(index)
self._table["profile"].update(ind)
self._table["raw_data"].update(ind)
def update(self,
reach_id=None,
profile_id=None,
solver_id=None,
timestamp=None):
if reach_id is not None: if reach_id is not None:
self.plot_xy.set_reach(reach_id) self.plot_xy.set_reach(reach_id)
self.plot_ac.set_reach(reach_id) self.plot_ac.set_reach(reach_id)
@@ -398,6 +432,15 @@ class ResultsWindow(PamhyrWindow):
self.update_table_selection_profile(profile_id) self.update_table_selection_profile(profile_id)
if solver_id is not None:
self.plot_xy.set_result(solver_id)
self.plot_ac.set_result(solver_id)
self.plot_rkc.set_result(solver_id)
self.plot_h.set_result(solver_id)
for plot in self._additional_plot:
self._additional_plot[plot].set_result(solver_id)
if timestamp is not None: if timestamp is not None:
self.plot_xy.set_timestamp(timestamp) self.plot_xy.set_timestamp(timestamp)
self.plot_ac.set_timestamp(timestamp) self.plot_ac.set_timestamp(timestamp)
@@ -458,6 +501,14 @@ class ResultsWindow(PamhyrWindow):
ind = indexes[0].row() ind = indexes[0].row()
self.update(profile_id=ind) self.update(profile_id=ind)
def _set_current_results(self):
table = self.find(QTableView, f"tableView_solver")
indexes = table.selectedIndexes()
if len(indexes) == 0:
return
self.update(solver_id=indexes[0].row())
def _set_current_timestamp(self): def _set_current_timestamp(self):
timestamp = self._timestamps[self._slider_time.value()] timestamp = self._timestamps[self._slider_time.value()]
self.update(timestamp=timestamp) self.update(timestamp=timestamp)
@@ -855,3 +906,38 @@ class ResultsWindow(PamhyrWindow):
) )
return my_dict return my_dict
#class CompareResultsWindow(ResultsWindow):
#_pamhyr_ui = "CompareResults"
#_pamhyr_name = "CompareResults"
#def _path_file(self, filename):
#return os.path.abspath(
#os.path.join(
#os.path.dirname(__file__),
#"..", "ui", "ressources", filename
#)
#)
#def __init__(self, study=None, config=None,
#solver=None, results=None,
#parent=None):
#self._solvers[0] = solver
#self._results = results
#trad = CompareResultsTranslate()
#name = (
#trad[self._pamhyr_name] + " - "
#+ study.name + " - "
#+ self._solvers[0].name
#)
#super(CompareResultsWindow, self).__init__(
#study=study,
#config=config,
#solver=solver,
#results=results,
#parent=parent,
#trad=trad
#)
+7 -3
View File
@@ -379,9 +379,13 @@ class ResultsWindowAdisTS(PamhyrWindow):
else: else:
pollutant = self._results.pollutants_list[indexes[0].row()] pollutant = self._results.pollutants_list[indexes[0].row()]
return (f"Reach: {reach.name} | " + #return (f"Reach: {reach.name} | " +
f"Profile: {pname} | " + #f"Profile: {pname} | " +
f"Pollutant: {pollutant}") #f"Pollutant: {pollutant}")
return (f"{self._trad['reach']}: {reach.name} | " +
f"{self._trad['cross_section']}: {pname} | " +
f"Pollutant: {pollutant} | " +
f"{self._trad['unit_time_s']} : {fts} ({ts} sec)")
def setup_statusbar(self): def setup_statusbar(self):
txt = self._compute_status_label() txt = self._compute_status_label()
+37 -1
View File
@@ -60,10 +60,14 @@ class ResultsTranslate(MainTranslate):
} }
self._sub_dict["table_headers_profile"] = { self._sub_dict["table_headers_profile"] = {
"name": self._dict["name"], "name": _translate("Results", "Profile name"),
"rk": self._dict["unit_rk"], "rk": self._dict["unit_rk"],
} }
self._sub_dict["table_headers_solver"] = {
"solver": _translate("Results", "Solver"),
}
self._sub_dict["table_headers_pollutants"] = { self._sub_dict["table_headers_pollutants"] = {
"name": _translate("Results", "Pollutant name"), "name": _translate("Results", "Pollutant name"),
} }
@@ -132,3 +136,35 @@ class ResultsTranslate(MainTranslate):
"unit_M": self._dict["unit_mass"], "unit_M": self._dict["unit_mass"],
"unit_thickness": self._dict["unit_thickness"], "unit_thickness": self._dict["unit_thickness"],
} }
class CompareResultsTranslate(ResultsTranslate):
def __init__(self):
super(CompareResultsTranslate, self).__init__()
self._dict['label_water'] = u"Δ "+_translate("Results", "Water elevation")
self._dict['unit_elevation'] = u"Δ "+self._dict["unit_elevation"]
self._sub_dict["table_headers_raw_data"] = {
"name": _translate("Results", "Profile"),
"water_elevation": u"Δ "+self._dict["unit_water_elevation"],
"discharge": u"Δ "+self._dict["unit_discharge"],
"velocity": u"Δ "+self._dict["unit_velocity"],
"width": u"Δ "+self._dict["unit_width"],
"depth": u"Δ "+self._dict["unit_depth"],
"mean_depth": u"Δ "+self._dict["unit_mean_depth"],
"wet_area": u"Δ "+self._dict["unit_wet_area"],
"wet_perimeter": u"Δ "+self._dict["unit_wet_perimeter"],
"hydraulic_radius": u"Δ "+self._dict["unit_hydraulic_radius"],
"froude": u"Δ "+self._dict["unit_froude"],
}
self._sub_dict["values_y"] = {
"bed_elevation": u"Δ "+self._dict["unit_bed_elevation"],
"water_elevation": u"Δ "+self._dict["unit_water_elevation"],
"discharge": u"Δ "+self._dict["unit_discharge"],
"velocity": u"Δ "+self._dict["unit_velocity"],
"depth": u"Δ "+self._dict["unit_depth"],
"mean_depth": u"Δ "+self._dict["unit_mean_depth"],
"froude": u"Δ "+self._dict["unit_froude"],
"wet_area": u"Δ "+self._dict["unit_wet_area"],
}
+101
View File
@@ -138,6 +138,107 @@ class SelectSolverWindow(PamhyrDialog):
super(SelectSolverWindow, self).accept() super(SelectSolverWindow, self).accept()
class CompareSolversWindow(PamhyrDialog):
_pamhyr_ui = "CompareSolvers"
_pamhyr_name = "Compare solvers"
def __init__(self, study=None, config=None,
parent=None):
self._solver1 = None
self._solver2 = None
name = _translate("Solver", "Compare solvers")
super(CompareSolversWindow, self).__init__(
title=name,
study=study,
config=config,
options=[],
parent=parent
)
self.setup_combobox1()
self.setup_combobox2()
self.setup_connections()
self.select_last_solver()
def setup_combobox1(self):
solvers = self._config.solvers
solvers_name = list(
map(
self._format_solver_name,
solvers
)
)
self.combobox_add_items("comboBox1", solvers_name)
def setup_combobox2(self):
solvers = self._config.solvers
solvers_name = list(
map(
self._format_solver_name,
solvers
)
)
self.combobox_add_items("comboBox2", solvers_name)
def setup_connections(self):
self.find(QPushButton, "pushButton_ok").clicked.connect(self.accept)
self.find(QPushButton, "pushButton_cancel")\
.clicked.connect(self.reject)
def select_last_solver(self):
solvers = self._config.solvers
last = self._config.last_solver_name
solver = list(
filter(
lambda s: s.name == last,
solvers
)
)
if len(solver) != 0:
self.set_combobox_text(
"comboBox1",
self._format_solver_name(solver[0])
)
def _format_solver_name(self, solver):
return f"{solver.name} - ({solver._type})"
@property
def solver1(self):
return self._solver1
@property
def solver2(self):
return self._solver2
def accept(self):
solver_name1 = self.get_combobox_text("comboBox1")
solver_name1 = solver_name1.rsplit(" - ", 1)[0]
self._solver1 = next(
filter(
lambda s: s.name == solver_name1,
self._config.solvers
)
)
solver_name2 = self.get_combobox_text("comboBox2")
solver_name2 = solver_name2.rsplit(" - ", 1)[0]
self._solver2 = next(
filter(
lambda s: s.name == solver_name2,
self._config.solvers
)
)
super(CompareSolversWindow, self).accept()
class SolverLogWindow(PamhyrWindow): class SolverLogWindow(PamhyrWindow):
_pamhyr_ui = "SolverLog" _pamhyr_ui = "SolverLog"
_pamhyr_name = "Solver Log" _pamhyr_name = "Solver Log"
+61
View File
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>80</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="locale">
<locale language="English" country="Europe"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QComboBox" name="comboBox1"/>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_ok">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="comboBox2"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+6
View File
@@ -161,6 +161,7 @@
</property> </property>
<addaction name="action_menu_results_last"/> <addaction name="action_menu_results_last"/>
<addaction name="action_open_results_from_file"/> <addaction name="action_open_results_from_file"/>
<addaction name="action_compare_results"/>
<addaction name="action_open_results_adists"/> <addaction name="action_open_results_adists"/>
</widget> </widget>
<widget class="QMenu" name="menu_help"> <widget class="QMenu" name="menu_help">
@@ -774,6 +775,11 @@
<string>DIF</string> <string>DIF</string>
</property> </property>
</action> </action>
<action name="action_compare_results">
<property name="text">
<string>Compare results</string>
</property>
</action>
<action name="action_open_results_adists"> <action name="action_open_results_adists">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
+7
View File
@@ -41,6 +41,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QTableView" name="tableView_solver"/>
</item>
</layout>
</widget>
</widget> </widget>
<widget class="QWidget" name="layoutWidget"> <widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
+1 -4
View File
@@ -46,9 +46,6 @@
<item> <item>
<widget class="QTableView" name="tableView_pollutants"/> <widget class="QTableView" name="tableView_pollutants"/>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_tot_left"/>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
@@ -457,7 +454,7 @@
<resources/> <resources/>
<connections/> <connections/>
<buttongroups> <buttongroups>
<buttongroup name="buttonGroup"/>
<buttongroup name="buttonGroup_2"/> <buttongroup name="buttonGroup_2"/>
<buttongroup name="buttonGroup"/>
</buttongroups> </buttongroups>
</ui> </ui>