Compare commits

...

65 Commits

Author SHA1 Message Date
Dylan Jeannin 83680bbe57 Pollutant: quickfix, back to previous version 2026-06-22 12:12:02 +02:00
Dylan Jeannin 1d1a00a0ff Pollutants: merge conflicts 2026-06-22 10:42:29 +02:00
Dylan Jeannin ffd95b9fdf Pollutants: merge conflicts 2026-06-22 10:42:07 +02:00
Pierre-Antoine 32cbc6bc3e Results: Fix additional geotiff display. 2026-06-16 17:28:55 +02:00
Pierre-Antoine 7d7a05c04c Results: Minor change. 2026-06-16 16:28:46 +02:00
Pierre-Antoine 6ac268b668 Results: Add data: Move update to plot class. 2026-06-16 16:24:05 +02:00
Pierre-Antoine 19c72892a8 Results: Add data: Hydrogram: Move drawing to plot. 2026-06-16 16:13:10 +02:00
Pierre-Antoine 9717968e08 Mage: LC: Fix export. 2026-06-10 14:26:05 +02:00
Pierre-Antoine e19c3229bd Solver: Mage: HS: Minor change. 2026-06-05 17:01:22 +02:00
Pierre-Antoine b3c6f1031b Solver: Mage: Minor change. 2026-06-05 16:35:57 +02:00
Pierre-Antoine c2d93b4a4a MainWindow: Finally connect action for the 'Quit' menu action. 2026-06-05 15:56:25 +02:00
Pierre-Antoine 76430322dd Results: Minor change. 2026-06-05 14:59:48 +02:00
Pierre-Antoine 31ae0ab8e0 Study: Add minor comment. 2026-06-05 10:54:51 +02:00
Pierre-Antoine 8182d434ec GeoTIFF: Fix crashes at 'cannot remove artist'. 2026-06-05 10:01:53 +02:00
Pierre-Antoine da78d0cdb1 AdisTS: Fix mage result workdir and add scenario into paths. 2026-06-04 15:21:03 +02:00
Pierre-Antoine 850db144ac WaitingDialog: Fix windows size. 2026-06-04 14:53:43 +02:00
Pierre-Antoine 0f6709075f Scenarios: Merge branch 'master' into scenarios. 2026-06-04 14:03:49 +02:00
Pierre-Antoine e86b84b0b9 AdisTS: Results: Fix db save. 2026-06-03 16:00:12 +02:00
Pierre-Antoine e08d212986 AdisTS: D90: Fix reach pid update. 2026-06-03 15:34:52 +02:00
Pierre-Antoine 7b88d955e5 Geometry: Update RK refactoring and fix modified flag. 2026-06-02 16:46:30 +02:00
Pierre-Antoine d1c34fb437 Pamhyr: Fix PEP8. 2026-06-02 15:40:51 +02:00
Pierre-Antoine 611f9cdfa3 Trad: Minor change. 2026-06-02 15:16:50 +02:00
Pierre-Antoine bd2fc22e96 Results: Fix non valid results save. 2026-06-02 15:11:07 +02:00
Pierre-Antoine efa16837d8 AdisTS: Minor change. 2026-05-28 17:09:02 +02:00
Pierre-Antoine db7aad26fd Geometry: Point: Optimize loading with indexing and update db to 0.2.5. 2026-05-28 17:09:02 +02:00
Pierre-Antoine 229b3da2d1 AdistTS: Fix update with table exists tests. 2026-05-28 17:09:02 +02:00
Theophile Terraz 0a0eeb3c3f debug 2026-05-07 17:01:22 +02:00
Theophile Terraz 539b63f765 update doc links 2026-04-28 10:09:24 +02:00
Theophile Terraz 19fedc2278 debug QSO export 2026-04-23 09:36:36 +02:00
Theophile Terraz f54dc07432 add warning windows in compare results 2026-04-22 11:38:51 +02:00
Theophile Terraz 3bbc55b4be add a warning window when opening Adis-TS results from file if wrong directory 2026-04-22 11:26:05 +02:00
Theophile Terraz c0d4aced5e debug 2026-04-07 11:47:45 +02:00
Theophile Terraz 421e6797f6 debug export csv 2026-04-03 14:18:29 +02:00
Theophile Terraz 0886956ec8 debug compare results with bedload 2026-04-03 13:51:15 +02:00
Theophile Terraz 9670bde56f add zfd in results 2026-04-03 12:30:58 +02:00
Theophile Terraz 3277cf551b start work on results buffers 2026-04-02 11:54:55 +02:00
Theophile Terraz ad5cc831a3 debug bed elevation comparison 2026-03-26 11:02:46 +01:00
Theophile Terraz 1f35020e3f update release to python3.12 2026-03-25 13:55:18 +01:00
Theophile Terraz 7ef41ad886 optimize results visu 2026-03-06 11:12:43 +01:00
Theophile Terraz ada396f26d debug 2026-03-05 16:46:22 +01:00
Theophile Terraz 674247db09 add talweg in update_rk 2026-03-04 11:14:05 +01:00
Theophile Terraz 5fecd29666 Claude François 2026-02-26 16:57:42 +01:00
Theophile Terraz 71e1324a0f debug open results from file 2026-02-24 17:19:59 +01:00
Theophile Terraz 07cae542b0 pep8 2026-02-24 09:18:47 +01:00
Theophile Terraz b693f67b99 debug RubarBE 2026-02-24 09:15:31 +01:00
Theophile Terraz 18a3d51d75 add adists with rubar3 + rubar3 in release 2026-02-23 10:46:05 +01:00
Theophile Terraz 118a39bd5c debug Rubar3 (from scenario branch) 2026-02-09 14:24:09 +01:00
Theophile Terraz 2009e8223b debug adists view 2026-01-30 11:32:06 +01:00
Theophile Terraz bdaa38ea5c Merge branch 'master' of gitlab.com:pamhyr/pamhyr2 2026-01-13 08:58:46 +01:00
Lionel Pénard 713732b1dd Fix doc links in README 2026-01-12 11:03:56 +01:00
Theophile Terraz f053539cdd debug 2025-12-19 11:29:02 +01:00
Theophile Terraz fc6916bb3e lot of debug 2025-12-12 14:18:09 +01:00
Theophile Terraz 97c26cb4fb debug HS 2025-12-12 11:33:13 +01:00
Theophile Terraz 10c98bb96e release for Jerome 2025-12-09 14:25:38 +01:00
Theophile Terraz 7c2d9891d0 debug IC 2025-12-05 16:51:39 +01:00
Theophile Terraz 3c3ac1f1df pep8 2025-12-05 10:19:43 +01:00
Theophile Terraz 80af278a0f add label in custom export results 2025-12-05 10:18:38 +01:00
Theophile Terraz f254eaee25 debug adists 2025-12-02 09:31:07 +01:00
Theophile Terraz 5adb0bdee5 debug GL in resluts 2025-11-28 15:31:07 +01:00
Theophile Terraz 64c99d46d4 debug named points in meshed profiles 2025-11-28 14:12:06 +01:00
Theophile Terraz 0f0defb36f Revert "debug ci"
This reverts commit 1e1ee67d4b.
2025-11-27 16:10:00 +01:00
Theophile Terraz 1e1ee67d4b debug ci 2025-11-27 16:03:09 +01:00
Theophile Terraz 5bc514c565 pep8 2025-11-26 11:58:58 +01:00
Theophile Terraz 1da3461dfe debug meshing 2025-11-26 11:16:19 +01:00
Theophile Terraz dd5eecb1e2 pep8 2025-11-24 15:18:28 +01:00
50 changed files with 872 additions and 294 deletions

View File

@ -186,7 +186,7 @@ unittest:
- pip3 install -r ./full-requirements.txt - pip3 install -r ./full-requirements.txt
- pip3 install -U -r ./full-requirements.txt - pip3 install -U -r ./full-requirements.txt
- cd src - cd src
- python3 -m unittest discover -t . - python3.12 -m unittest discover -t .
test-pep8: test-pep8:
stage: test stage: test

View File

@ -3,7 +3,7 @@
Pamhyr is a free and open source graphical user interface for 1D hydro-sedimentary Pamhyr is a free and open source graphical user interface for 1D hydro-sedimentary
modelling of rivers. modelling of rivers.
![logo](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/raw/master/src/View/ui/ressources/Pamhyr2_logo.png) ![logo](https://gitlab.com/pamhyr/pamhyr2/-/raw/master/src/View/ui/ressources/Pamhyr2_logo.png)
## Features ## Features
@ -21,9 +21,9 @@ modelling of rivers.
+ Create and edit study alternative scenario tree + Create and edit study alternative scenario tree
Let see the Let see the
[documentation](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home) [documentation](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home)
([:fr:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home-fr), ([:fr:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home-fr),
[:gb:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home-en)) [:gb:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home-en))
for more details. for more details.
## Install ## Install
@ -31,11 +31,11 @@ for more details.
### GNU/Linux ### GNU/Linux
See documentation: See documentation:
- [French :fr:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/fr/Install%20on%20GNULinux) - [French :fr:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/fr/Install%20on%20GNULinux)
- [English :gb:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/en/Install%20on%20GNULinux) - [English :gb:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/en/Install%20on%20GNULinux)
### Windows ### Windows
See documentation: See documentation:
- [French :fr:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/fr/Install%20on%20Windows) - [French :fr:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/fr/Install%20on%20Windows)
- [English :gb:](https://gitlab.irstea.fr/theophile.terraz/pamhyr/-/wikis/home/en/Install%20on%20Windows) - [English :gb:](https://gitlab.com/pamhyr/pamhyr2/-/wikis/home/en/Install%20on%20Windows)

View File

@ -14,3 +14,4 @@ platformdirs>=4.2.0
pyshp>=2.3.1 pyshp>=2.3.1
rasterio==1.3.11 rasterio==1.3.11
#fortranformat==2.0.3 #fortranformat==2.0.3

View File

@ -66,7 +66,6 @@ class InternalMeshing(AMeshingTool):
return new_profiles return new_profiles
def st_to_m(self, profiles, guide_list): def st_to_m(self, profiles, guide_list):
guide_list = ["un"] + guide_list + ["np"] guide_list = ["un"] + guide_list + ["np"]
max_values = [0] * (len(guide_list) - 1) max_values = [0] * (len(guide_list) - 1)
max_values_index = [0] * (len(guide_list) - 1) max_values_index = [0] * (len(guide_list) - 1)
@ -85,11 +84,13 @@ class InternalMeshing(AMeshingTool):
profiles[isect+1], profiles[isect+1],
guide_list[i], guide_list[i],
guide_list[i+1]) guide_list[i+1])
for isect in reversed(range(0, max_values_index[i])): for isect in reversed(range(0, max_values_index[i])):
self.compl_sect(profiles[isect+1], self.compl_sect(profiles[isect+1],
profiles[isect], profiles[isect],
guide_list[i], guide_list[i],
guide_list[i+1]) guide_list[i+1])
return profiles return profiles
def interpolate_transversal_step(self, def interpolate_transversal_step(self,
@ -129,6 +130,7 @@ class InternalMeshing(AMeshingTool):
p.name = f'interpol{p.rk}' p.name = f'interpol{p.rk}'
new_profiles2.append(p) new_profiles2.append(p)
new_profiles.append(new_profiles2) new_profiles.append(new_profiles2)
return new_profiles return new_profiles
def compl_sect(self, sect1, sect2, tag1, tag2): def compl_sect(self, sect1, sect2, tag1, tag2):
@ -243,8 +245,9 @@ class InternalMeshing(AMeshingTool):
sect2.point(start2+len2).name = '' sect2.point(start2+len2).name = ''
if tag1 != "un": if tag1 != "un":
sect2.point(start2).name = tag1 sect2.point(start2).name = tag1
if tag1 != "np": if tag2 != "np":
sect2.point(start2+len2).name = tag2 sect2.point(start2+len2).name = tag2
sect2.modified() sect2.modified()
def update_rk(self, reach, begin_rk, end_rk, def update_rk(self, reach, begin_rk, end_rk,

View File

@ -248,15 +248,13 @@ class BoundaryConditionAdisTS(SQLSubModel):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False created = False
if major == "0" and minor == "0": if major == "0" and int(minor) < 2:
if int(release) < 11: if cls.is_table_exists(execute, "boundary_condition_adists"):
cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute) cls._db_create(execute)
created = True created = True
if major == "0" and int(minor) < 2:
if not created:
cls._db_update_to_0_2_0(execute, data)
if not created: if not created:
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)

View File

@ -73,15 +73,13 @@ class D90AdisTS(SQLSubModel):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False created = False
if major == "0" and minor == "0": if major == "0" and int(minor) < 2:
if int(release) < 11: if cls.is_table_exists(execute, "d90_adists"):
cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute) cls._db_create(execute)
created = True created = True
if major == "0" and int(minor) < 2:
if not created:
cls._db_update_to_0_2_0(execute, data)
if not created: if not created:
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)

View File

@ -70,16 +70,12 @@ class D90AdisTSSpec(SQLSubModel):
@classmethod @classmethod
def _db_update(cls, execute, version, data=None): def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(execute, "d90_spec"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True return True
@ -87,6 +83,7 @@ class D90AdisTSSpec(SQLSubModel):
def _db_update_to_0_2_0(cls, execute, data): def _db_update_to_0_2_0(cls, execute, data):
table = "d90_spec" table = "d90_spec"
table_new = "d90_adists_spec" table_new = "d90_adists_spec"
reachs = data['id2pid']['river_reach']
cls.update_db_add_pamhyr_id(execute, table, data) cls.update_db_add_pamhyr_id(execute, table, data)
Scenario.update_db_add_scenario(execute, table) Scenario.update_db_add_scenario(execute, table)
@ -106,6 +103,7 @@ class D90AdisTSSpec(SQLSubModel):
execute(f"ALTER TABLE {table_new}_tmp RENAME TO {table_new}") execute(f"ALTER TABLE {table_new}_tmp RENAME TO {table_new}")
cls._db_update_to_0_2_0_set_d90_pid(execute, data) cls._db_update_to_0_2_0_set_d90_pid(execute, data)
cls._db_update_to_0_2_0_set_reach_pid(execute, table_new, reachs)
@classmethod @classmethod
def _db_update_to_0_2_0_set_d90_pid(cls, execute, data): def _db_update_to_0_2_0_set_d90_pid(cls, execute, data):

View File

@ -79,15 +79,13 @@ class DIFAdisTS(SQLSubModel):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False created = False
if major == "0" and minor == "0": if major == "0" and int(minor) < 2:
if int(release) < 11: if cls.is_table_exists(execute, "dif_adists"):
cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute) cls._db_create(execute)
created = True created = True
if major == "0" and int(minor) < 2:
if not created:
cls._db_update_to_0_2_0(execute, data)
if not created: if not created:
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)

View File

@ -34,15 +34,13 @@ class DIFAdisTSSpec(SQLSubModel):
def __init__(self, id: int = -1, method: str = "", def __init__(self, id: int = -1, method: str = "",
status=None, owner_scenario=-1): status=None, owner_scenario=-1):
super(DIFAdisTSSpec, self).__init__() super(DIFAdisTSSpec, self).__init__(
id=id, status=status,
owner_scenario=owner_scenario
)
self._status = status self._status = status
if id == -1:
self._id = DIFAdisTSSpec._id_cnt
else:
self._id = id
self._method = method self._method = method
self._reach = None self._reach = None
self._start_rk = None self._start_rk = None
@ -52,8 +50,6 @@ class DIFAdisTSSpec(SQLSubModel):
self._c = None self._c = None
self._enabled = True self._enabled = True
DIFAdisTSSpec._id_cnt = max(DIFAdisTSSpec._id_cnt + 1, self._id)
@classmethod @classmethod
def _db_create(cls, execute, ext=""): def _db_create(cls, execute, ext=""):
execute(f""" execute(f"""
@ -81,16 +77,12 @@ class DIFAdisTSSpec(SQLSubModel):
@classmethod @classmethod
def _db_update(cls, execute, version, data=None): def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(execute, "dif_spec"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True return True

View File

@ -365,3 +365,9 @@ class Friction(SQLSubModel):
# self.end_strickler.medium]) # self.end_strickler.medium])
return minor, medium return minor, medium
def update_rks(self, begin_rk, end_rk):
self._begin_rk = begin_rk
self._end_rk = end_rk
self.modified()

View File

@ -66,6 +66,11 @@ class PointXYZ(Point):
) )
""") """)
execute(
"CREATE INDEX idx_point " +
"ON geometry_pointXYZ(profile, scenario);"
)
return cls._create_submodel(execute) return cls._create_submodel(execute)
@classmethod @classmethod
@ -90,6 +95,13 @@ 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":
if int(release) < 5:
execute(
"CREATE INDEX idx_point " +
"ON geometry_pointXYZ(profile, scenario);"
)
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)
@classmethod @classmethod

View File

@ -1098,6 +1098,7 @@ class ProfileXYZ(Profile, SQLSubModel):
rk=self.rk, rk=self.rk,
reach=self.reach, reach=self.reach,
status=self._status) status=self._status)
for i, k in enumerate(self.points): for i, k in enumerate(self.points):
p.insert_point(i, k.copy()) p.insert_point(i, k.copy())

View File

@ -967,3 +967,9 @@ class Reach(SQLSubModel):
break break
return global_index return global_index
def update_rks(self, rks):
for rk, profile in zip(rks, self.profiles):
profile.rk = rk
self.modified()

View File

@ -79,16 +79,12 @@ class InitialConditionsAdisTS(SQLSubModel):
@classmethod @classmethod
def _db_update(cls, execute, version, data=None): def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(execute, "initial_conditions_adists"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True return True

View File

@ -77,16 +77,12 @@ class ICAdisTSSpec(SQLSubModel):
@classmethod @classmethod
def _db_update(cls, execute, version, data=None): def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(execute, "initial_conditions_adists_spec"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True return True

View File

@ -69,14 +69,12 @@ class Data(SQLSubModel):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(
execute, "lateral_contribution_data_adists"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True return True
@ -243,15 +241,13 @@ class LateralContributionAdisTS(SQLSubModel):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False created = False
if major == "0" and minor == "0": if major == "0" and int(minor) < 2:
if int(release) < 11: if cls.is_table_exists(execute, "lateral_contribution_adists"):
cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute) cls._db_create(execute)
created = True created = True
if major == "0" and int(minor) < 2:
if not created:
cls._db_update_to_0_2_0(execute, data)
if not created: if not created:
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)

View File

@ -95,16 +95,12 @@ class OutputRKAdists(SQLSubModel):
@classmethod @classmethod
def _db_update(cls, execute, version, data=None): def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(execute, "OutputRKAdists"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return True return True

View File

@ -138,16 +138,12 @@ class PollutantCharacteristics(SQLSubModel):
@classmethod @classmethod
def _db_update(cls, execute, version, data=None): def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False
if major == "0" and minor == "0":
if int(release) < 11:
cls._db_create(execute)
created = True
if major == "0" and int(minor) < 2: if major == "0" and int(minor) < 2:
if not created: if cls.is_table_exists(execute, "Pollutants_characteristics"):
cls._db_update_to_0_2_0(execute, data) cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute)
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)
@ -371,15 +367,13 @@ class Pollutants(SQLSubModel):
major, minor, release = version.strip().split(".") major, minor, release = version.strip().split(".")
created = False created = False
if major == "0" and minor == "0": if major == "0" and int(minor) < 2:
if int(release) < 11: if cls.is_table_exists(execute, "Pollutants"):
cls._db_update_to_0_2_0(execute, data)
else:
cls._db_create(execute) cls._db_create(execute)
created = True created = True
if major == "0" and int(minor) < 2:
if not created:
cls._db_update_to_0_2_0(execute, data)
if major == "0" and minor == "2": if major == "0" and minor == "2":
if int(release) < 5: if int(release) < 5:
execute(f"ALTER TABLE pollutants " + execute(f"ALTER TABLE pollutants " +

View File

@ -312,7 +312,7 @@ class Reservoir(SQLSubModel):
new_reservoir._node = next( new_reservoir._node = next(
filter( filter(
lambda n: n.id == node_id, data["nodes"] lambda n: n.id == node_id, data["nodes"]
) ), None
) )
data["reservoir"] = new_reservoir data["reservoir"] = new_reservoir

View File

@ -349,10 +349,16 @@ class Results(SQLSubModel):
f"AND result = {pid}" f"AND result = {pid}"
) )
def _is_valid(self):
return "timestamps" in self._meta_data
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
if self._status.scenario.id != self._owner_scenario: if self._status.scenario.id != self._owner_scenario:
return True return True
if not self._is_valid():
return False
pid = self._pamhyr_id pid = self._pamhyr_id
if self._solver is None: if self._solver is None:
solver_name = self.get("solver_name") solver_name = self.get("solver_name")

View File

@ -21,12 +21,13 @@ import os
from copy import deepcopy from copy import deepcopy
from datetime import datetime from datetime import datetime
from Model.Tools.PamhyrDB import SQLSubModel
from Model.Results.River.RiverAdisTS import River from Model.Results.River.RiverAdisTS import River
logger = logging.getLogger() logger = logging.getLogger()
class Results(object): class Results(SQLSubModel):
def __init__(self, study=None, solver=None, def __init__(self, study=None, solver=None,
repertory="", name="0", type_pol=None): repertory="", name="0", type_pol=None):
self._study = study self._study = study
@ -90,3 +91,6 @@ class Results(object):
self._repertory, self._repertory,
qlog=None, qlog=None,
) )
def _db_save(self, execute, data=None):
return False

View File

@ -520,6 +520,9 @@ class Study(SQLModel):
[self.scenarios, self._river] [self.scenarios, self._river]
) )
logger.debug(cnt) logger.debug(cnt)
# HACK: 8 is the number of SQL request do and dont counted in
# submodel save_count (let's count sql execute into the
# '_save' method)
return cnt + 8 return cnt + 8
def close(self): def close(self):

View File

@ -301,6 +301,15 @@ class SQLSubModel(PamhyrID):
""" """
raise NotImplementedMethodeError(cls, cls._db_update) raise NotImplementedMethodeError(cls, cls._db_update)
@classmethod
def is_table_exists(cls, execute, table):
return any(
execute(
"SELECT name FROM sqlite_master " +
f"WHERE type='table' AND name='{table}'"
)
)
@classmethod @classmethod
def _db_update_to_0_2_0_set_node_pid(cls, execute, table, nodes): def _db_update_to_0_2_0_set_node_pid(cls, execute, table, nodes):
els = execute( els = execute(

View File

@ -164,13 +164,194 @@ class AdisTS(CommandLineSolver):
return lst return lst
def input_param(self): def input_param(self):
name = self._study.name name = self._study.name.replace(" ", "_")
return f"{name}.REP" return f"{name}.REP"
def log_file(self): def log_file(self):
name = self._study.name name = self._study.name.replace(" ", "_")
return f"{name}.TRA" return f"{name}.TRA"
def _export_ST(self, study, repertory, qlog, name="0"):
files = []
if qlog is not None:
qlog.put("Export ST file")
os.makedirs(os.path.join(repertory, "net"), exist_ok=True)
# Write header
edges = study.river.enable_edges()
for edge in edges:
name = f"Reach_{edge.id + 1:>3}".replace(" ", "0")
with adists_file_open(
os.path.join(repertory, "net", f"{name}.ST"),
"w+"
) as f:
files.append(str(os.path.join("net", f"{name}.ST")))
cnt_num = 1
for profile in edge.reach.profiles:
self._export_ST_profile_header(
f, files, profile, cnt_num
)
cnt_num += 1
# Points
for point in profile.points:
self._export_ST_point_line(
f, files, point
)
# Profile last line
f.write(f" 999.9990 999.9990 999.9990\n")
def _export_ST_profile_header(self, wfile, files,
profile, cnt):
num = f"{cnt:>6}"
c1 = f"{profile.code1:>6}"
c2 = f"{profile.code2:>6}"
t = f"{len(profile.points):>6}"
rk = f"{profile.rk:>12f}"[0:12]
pname = profile.name
if profile.name == "":
# Generate name from profile id prefixed with
# 'p' (and replace space char with '0' char)
pname = f"p{profile.id:>3}".replace(" ", "0")
name = f"{pname:<19}"
# Generate sediment additional data if available
sediment = ""
if profile.sl is not None:
if not any(filter(lambda f: ".GRA" in f, files)):
files.append(self._gra_file)
# Number of layers
nl = len(profile.sl)
sediment = f" {nl:>3}"
# Layers data
for layer in profile.sl.layers:
sediment += (
f" {layer.height:>10} {layer.d50:>10} " +
f"{layer.sigma:>10} " +
f"{layer.critical_constraint:>10}"
)
# Profile header line
wfile.write(f"{num}{c1}{c2}{t} {rk} {pname} {sediment}\n")
def _export_ST_point_line(self, wfile, files, point):
x = f"{point.x:<12.4f}"[0:12]
y = f"{point.y:<12.4f}"[0:12]
z = f"{point.z:<12.4f}"[0:12]
n = f"{point.name:<3}"
# Generate sediment additional data if available
sediment = ""
prev = point.z
if point.sl is not None:
# Number of layers
nl = len(point.sl)
sediment = f"{nl:>3}"
# Layers data
for layer in point.sl.layers:
prev = round(prev - layer.height, 5)
sediment += (
f" {prev:>10} {layer.d50:>10} " +
f"{layer.sigma:>10} " +
f"{layer.critical_constraint:>10}"
)
# Point line
wfile.write(f"{x} {y} {z} {n} {sediment}\n")
def _export_NET(self, study, repertory, qlog=None, name="0"):
if qlog is not None:
qlog.put("Export NET file")
with adists_file_open(
os.path.join(repertory, f"{name}.NET"), "w+") as f:
edges = study.river.enable_edges()
for e in edges:
name = f"Reach_{e.id + 1:>3}".replace(" ", "0")
id = name
n1 = f"{e.node1.id:3}".replace(" ", "x")
n2 = f"{e.node2.id:3}".replace(" ", "x")
file = os.path.join("net", name + ".ST")
f.write(f"{id} {n1} {n2} {file}\n")
def _export_fake_INI(self, study, repertory, qlog=None, name="0"):
if qlog is not None:
qlog.put("Export fake INI file")
with adists_file_open(
os.path.join(
repertory, "Mage_fin.ini"
), "w+"
) as f:
edges = study.river.enable_edges()
for i, edge in enumerate(edges):
lst = list(filter(
lambda f: f.is_full_defined(),
edge.frictions.frictions
))
rk_min = 9999999.9
rk_max = -9999999.9
coeff_min = -1.0
coeff_max = -1.0
for s in lst: # TODO optimise ?
if s.begin_rk > rk_max:
rk_max = s.begin_rk
coeff_max = s.begin_strickler
if s.begin_rk < rk_min:
rk_min = s.begin_rk
coeff_min = s.begin_strickler
if s.end_rk > rk_max:
rk_max = s.end_rk
coeff_max = s.end_strickler
if s.end_rk < rk_min:
rk_min = s.end_rk
coeff_min = s.end_strickler
print("min max", rk_min, rk_max)
def get_stricklers_from_rk(rk, lst):
print("rk", rk)
coeff = None
if rk > rk_max:
coeff = coeff_max
elif rk < rk_min:
coeff = coeff_min
else:
for s in lst:
if (rk >= s.begin_rk and rk <= s.end_rk or
rk <= s.begin_rk and rk >= s.end_rk):
coeff = s.begin_strickler # TODO: inerpolate
break
# TODO interpolation if rk is not in frictons
if coeff is None:
logger.error(
"Study frictions are not fully defined"
)
return None
return coeff.minor, coeff.medium
for j, profile in enumerate(edge.reach.profiles):
coef_min, coef_moy = get_stricklers_from_rk(profile.rk,
lst)
f.write(
f" {i+1:3}{j+1:4}{' '*116}{coef_min:9}{coef_moy:9}\n")
def _export_REP_additional_lines(self, study, rep_file): def _export_REP_additional_lines(self, study, rep_file):
lines = filter( lines = filter(
lambda line: line.is_enabled(), lambda line: line.is_enabled(),
@ -192,7 +373,7 @@ class AdisTS(CommandLineSolver):
), "w+" ), "w+"
) as f: ) as f:
path = os.path.join("..", mage_rep, name) path = os.path.join("..", mage_rep, name)
f.write(f"NET {path}.NET\n") f.write(f"NET {name}.NET\n")
f.write(f"REP {path}.REP\n") f.write(f"REP {path}.REP\n")
for file in files: for file in files:
@ -201,13 +382,25 @@ class AdisTS(CommandLineSolver):
self._export_REP_additional_lines(study, f) self._export_REP_additional_lines(study, f)
path_mage_net = os.path.join(os.path.abspath( self._export_ST(study, repertory, qlog, name=name)
os.path.join(repertory, os.pardir) self._export_NET(study, repertory, qlog, name=name)
), os.path.join(mage_rep, "net"))
path_adists_net = os.path.join(repertory, "net")
if os.path.exists(path_mage_net): # fake mage_fin.ini:
shutil.copytree(path_mage_net, path_adists_net, dirs_exist_ok=True)
path_mage = os.path.join(os.path.abspath(
os.path.join(repertory, os.pardir)), mage_rep)
self._export_fake_INI(study, path_mage,
qlog, name=name)
# path_mage_net = os.path.join(os.path.abspath(
# os.path.join(repertory, os.pardir)
# ), os.path.join(mage_rep, "net"))
# path_adists_net = os.path.join(repertory, "net")
# if os.path.exists(path_mage_net):
# shutil.copytree(path_mage_net,
# path_adists_net,
# dirs_exist_ok=True)
@timer @timer
def export(self, study, repertory, qlog=None): def export(self, study, repertory, qlog=None):

View File

@ -386,26 +386,26 @@ class Mage(CommandLineSolver):
return files return files
def _export_LC(self, study, lateral, f, qlog, name="0"): def _export_LC(self, study, lateral, f, qlog, name="0"):
if lateral.edge is None: if lateral.reach is None:
return return
if lateral.is_deleted(): if lateral.is_deleted():
return return
edges = study.river.enable_edges() edges = study.river.enable_edges()
if lateral.edge not in edges: if lateral.reach not in edges:
return return
eid, _ = next( eid, _ = next(
filter( filter(
lambda e: e[1] == lateral.edge, lambda e: e[1] == lateral.reach,
enumerate(edges) enumerate(edges)
) )
) )
name = f"{eid+1:>3}" name = f"{eid+1:>3}"
# name = f"Reach_{lateral.edge.id + 1:>3}".replace(" ", "0") # name = f"Reach_{lateral.reach.id + 1:>3}".replace(" ", "0")
f.write(f"* {lateral.edge.name} ({name}) {lateral.lctype}\n") f.write(f"* {lateral.reach.name} ({name}) {lateral.lctype}\n")
f.write( f.write(
f"${name} " + f"${name} " +
f"{lateral.begin_rk:>10.4f} {lateral.end_rk:>10.4f}\n" f"{lateral.begin_rk:>10.4f} {lateral.end_rk:>10.4f}\n"
@ -546,6 +546,15 @@ class Mage(CommandLineSolver):
return files return files
def skip_hs(self, hs):
return (
hs.input_reach is None
or not hs.input_reach.is_enable()
or not hs.enabled
or hs.input_section is None
or hs.is_deleted()
)
def _export_SIN(self, study, repertory, qlog, name="0"): def _export_SIN(self, study, repertory, qlog, name="0"):
files = [] files = []
@ -571,19 +580,7 @@ class Mage(CommandLineSolver):
files.append(f"{name}.SIN") files.append(f"{name}.SIN")
for hs in hydraulic_structures: for hs in hydraulic_structures:
if hs.input_reach is None: if self.skip_hs(hs):
continue
if not hs.input_reach.is_enable():
continue
if not hs.enabled:
continue
if hs.input_section is None:
continue
if hs.is_deleted():
continue continue
f.write( f.write(
@ -1186,7 +1183,7 @@ class Mage8(Mage):
for p in r.profiles: for p in r.profiles:
p.geometry.compute_tabulation() p.geometry.compute_tabulation()
logger.info(f"compute velocily...") logger.info(f"compute velocity...")
for r in reachs: for r in reachs:
for t in ts_list: for t in ts_list:

View File

@ -58,12 +58,12 @@ class Rubar3(CommandLineSolver):
("rubarbe_iovis", "n"), ("rubarbe_iovis", "n"),
("rubarbe_rep", "n"), ("rubarbe_rep", "n"),
("rubarbe_tinit", "000:00:00:00"), ("rubarbe_tinit", "000:00:00:00"),
("rubarbe_tmax", "999:99:99:00"), ("rubarbe_tmax", "000:01:00:00"), # 1 day
("rubarbe_tiopdt", "000:00:00:00"), ("rubarbe_tiopdt", "000:00:00:00"),
("rubarbe_dt", "5.0"), ("rubarbe_dt", "5.0"),
("rubarbe_ts", "999:99:99:00"), ("rubarbe_ts", "999:99:99:00"),
("rubarbe_dtsauv", "00:00:00:05"), ("rubarbe_dtsauv", "00:00:05:00"),
("rubarbe_psave", "00:00:00:05"), ("rubarbe_psave", "00:00:05:00"),
("rubarbe_fdeb1", "1"), ("rubarbe_fdeb1", "1"),
("rubarbe_fdeb2", "10"), ("rubarbe_fdeb2", "10"),
("rubarbe_fdeb3", "100"), ("rubarbe_fdeb3", "100"),
@ -610,6 +610,28 @@ class Rubar3(CommandLineSolver):
) )
ts = set() ts = set()
timestamp = next(filter(
lambda p: p.name == 'rubarbe_tinit',
study.river.get_params(self._type).parameters
)).value
if timestamp.count(':') == 3:
timestamp = old_pamhyr_date_to_timestamp(timestamp)
ts.add(timestamp)
# add initial condition
for r, edge in enumerate(study.river.enable_edges()):
reach = edge.reach
ics = study.river.initial_conditions.get(edge)
q = ics.get_discharge()
z = ics.get_elevation()
k = 0
for i, j in zip(z, q):
v = reach.profiles[k].speed(i, j)
set_and_compute_limites(reachs[r][0], k, i, j, v)
k += 1
# start read
end = False end = False
while True: while True:
line = f.readline() line = f.readline()
@ -649,6 +671,97 @@ class Rubar3(CommandLineSolver):
h, s, q, z = read_data_line(f) h, s, q, z = read_data_line(f)
set_and_compute_limites(reach, ind, z+h, q, s) set_and_compute_limites(reach, ind, z+h, q, s)
@timer
def write_bin(self, study, fname, results, qlog=None, name="0"):
logger.info(f"write_bin: Start writing '{fname}' ...")
with open(fname, "wb") as f:
def newline(j): return np.asarray([j], dtype=np.int32).tofile(f)
def endline(j): return np.asarray([j], dtype=np.int32).tofile(f)
def write_int(i):
newline(len(i)*4)
np.array(i, dtype=np.int32).tofile(f)
endline(len(i)*4)
def write_float(i):
newline(len(i)*4)
np.array(i, dtype=np.float32).tofile(f)
endline(len(i)*4)
def write_float64(i):
newline(len(i)*8)
np.array(i, dtype=np.float64).tofile(f)
endline(len(i)*8)
def write_float64(i):
newline(len(i)*8)
np.array(i, dtype=np.float64).tofile(f)
endline(len(i)*8)
def write_data(npts, t, a, val):
newline(npts*4 + 13)
np.array(npts, dtype=np.int32).tofile(f)
np.array(t, dtype=np.float64).tofile(f)
np.array(bytearray(a.encode()), dtype=np.byte).tofile(f)
np.array(val, dtype=np.float32).tofile(f)
endline(npts*4 + 13)
ts_list = sorted(results.get("timestamps"))
profiles = []
for r in results.river.reachs:
profiles += r.profiles
# Meta data (1st line)
nb_reach = len(results.river)
nb_profile = len(profiles)
write_int([nb_reach, nb_profile, "82"])
# Reach information (2nd line)
is1 = []
is2 = []
ltmp = []
i = 1
for r in results.river.reachs:
j = i+len(r)-1
ltmp += [i, j]
is1.append(i)
is2.append(j)
i += i+len(r)
write_int(ltmp)
# X (3rd line)
rk = []
for r in results.river.reachs:
rk += r.geometry.get_rk()
write_float(rk)
# Z and Y (4th line)
# ltmp = []
# for r in results.river.reachs:
# for p in r.prifiles:
# ltpm.append(p.rk)
write_float(3*nb_profile*[0.0])
# Data
for timestamp in ts_list:
q = list(
map(
lambda p: p.get_ts_key(timestamp, "Q"),
profiles
)
)
write_data(nb_profile, timestamp, "Q", q)
z = list(
map(
lambda p: p.get_ts_key(timestamp, "Z"),
profiles
)
)
write_data(nb_profile, timestamp, "Z", z)
logger.info(f"write_bin: ... end with {len(ts_list)} timestamps")
@timer @timer
def results(self, study, repertory, qlog=None, name=None): def results(self, study, repertory, qlog=None, name=None):
results = Results( results = Results(

View File

@ -16,7 +16,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from tools import trace, timer from tools import trace, timer, logger_exception
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAction, QListView, QVBoxLayout, QAction, QListView, QVBoxLayout,
@ -134,7 +134,10 @@ class GeoTIFFListWindow(PamhyrWindow):
def _update_rectangle(self): def _update_rectangle(self):
for rect in self._plot_rect: for rect in self._plot_rect:
rect.remove() try:
rect.remove()
except Exception as e:
logger_exception(e)
self._plot_rect = [] self._plot_rect = []

View File

@ -247,14 +247,13 @@ class UpdateRKCommand(QUndoCommand):
self._new_end_rk = None self._new_end_rk = None
def undo(self): def undo(self):
for rk, profile in zip(self._rks, self._reach.profiles):
profile.rk = rk self._reach.update_rks(self._rks)
for begin_rk, end_rk, friction in zip(self._begin_rk, for begin_rk, end_rk, friction in zip(self._begin_rk,
self._end_rk, self._end_rk,
self._frictions): self._frictions):
friction.begin_rk = begin_rk friction.update_rks(begin_rk, end_rk)
friction.end_rk = end_rk
def redo(self): def redo(self):
if self._new_rks is None: if self._new_rks is None:
@ -264,13 +263,12 @@ class UpdateRKCommand(QUndoCommand):
**self._data **self._data
) )
for rk, profile in zip(self._new_rks, self._reach.profiles): self._reach.update_rks(self._new_rks)
profile.rk = rk
for begin_rk, end_rk, friction in zip(self._new_begin_rk, for begin_rk, end_rk, friction in zip(self._new_begin_rk,
self._new_end_rk, self._new_end_rk,
self._frictions): self._frictions):
friction.begin_rk = begin_rk friction.update_rks(begin_rk, end_rk)
friction.end_rk = end_rk
class MeshingCommand(QUndoCommand): class MeshingCommand(QUndoCommand):

View File

@ -302,7 +302,6 @@ class GeometryWindow(PamhyrWindow):
self.tableView.model().blockSignals(False) self.tableView.model().blockSignals(False)
def edit_meshing(self): def edit_meshing(self):
rows = list( rows = list(
set( set(
(i.row() for i in self.tableView.selectedIndexes()) (i.row() for i in self.tableView.selectedIndexes())
@ -326,6 +325,25 @@ class GeometryWindow(PamhyrWindow):
logger_exception(e) logger_exception(e)
return return
ind = []
for i in range(self._reach.number_profiles):
if self._reach.profile(i).rk in selected_rk:
ind.append(i)
self.tableView.setFocus()
selection = self.tableView.selectionModel()
index = QItemSelection()
if len(ind) > 0:
for i in ind:
index.append(QItemSelectionRange(
self.tableView.model().index(i, 0))
)
selection.select(
index,
QItemSelectionModel.Rows |
QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Select
)
def _edit_meshing(self, data): def _edit_meshing(self, data):
try: try:
mesher = InternalMeshing() mesher = InternalMeshing()
@ -371,9 +389,6 @@ class GeometryWindow(PamhyrWindow):
except Exception as e: except Exception as e:
logger_exception(e) logger_exception(e)
raise ExternFileMissingError( raise ExternFileMissingError(
module="mage",
filename="MailleurTT",
path=MeshingWithMageMailleurTT._path(),
src_except=e src_except=e
) )

View File

@ -53,7 +53,8 @@ class LCTranslate(MainTranslate):
self._dict["y"] = _translate("Geometry", "Y (m)") self._dict["y"] = _translate("Geometry", "Y (m)")
self._dict["z"] = _translate("Geometry", "Z (m)") self._dict["z"] = _translate("Geometry", "Z (m)")
self._dict["file_lat"] = _translate( self._dict["file_lat"] = _translate(
"LateralContribution", "Shapefile (*.LAT *.lat)") "LateralContribution",
"Mage lateral contributions file (*.LAT *.lat)")
self._dict["file_all"] = _translate( self._dict["file_all"] = _translate(
"LateralContribution", "All files (*)") "LateralContribution", "All files (*)")

View File

@ -299,6 +299,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_rep_additional_lines": self.open_rep_lines, "action_menu_rep_additional_lines": self.open_rep_lines,
"action_menu_edit_geotiff": self.open_geotiff, "action_menu_edit_geotiff": self.open_geotiff,
"action_menu_close": self.close_model, "action_menu_close": self.close_model,
"action_menu_quit": self.close,
"action_menu_results_last": self.open_last_results, "action_menu_results_last": self.open_last_results,
"action_menu_open_results_from_file": self.open_results_from_file, "action_menu_open_results_from_file": self.open_results_from_file,
"action_menu_compare_scenarios_results": "action_menu_compare_scenarios_results":
@ -2006,6 +2007,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if res.river.reach(r).has_bedload(): if res.river.reach(r).has_bedload():
res.river.reach(r).bufferize(ts, "zfd") res.river.reach(r).bufferize(ts, "zfd")
for res in (result3, result4, result5):
for r in range(int(res.get("nb_reach"))):
for key in ["Z", "Q", "V"]:
res.river.reach(r).bufferize(ts, key)
if res.river.reach(r).has_bedload():
res.river.reach(r).bufferize(ts, "zfd")
return [result4, result5, result3] return [result4, result5, result3]
def open_results_adists(self): def open_results_adists(self):

View File

@ -19,7 +19,7 @@
from View.Tools.PamhyrWindow import PamhyrDialog from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QRadioButton, QCheckBox, QVBoxLayout, QLabel, QRadioButton, QCheckBox, QVBoxLayout, QLabel, QFrame
) )
from View.Results.translate import ResultsTranslate from View.Results.translate import ResultsTranslate
@ -43,6 +43,7 @@ class CustomExportDialog(PamhyrDialog):
self.setup_radio_buttons_x() self.setup_radio_buttons_x()
self.setup_radio_buttons_res() self.setup_radio_buttons_res()
self.setup_label()
self.setup_envelop_box() self.setup_envelop_box()
self.setup_check_boxes() self.setup_check_boxes()
@ -87,6 +88,22 @@ class CustomExportDialog(PamhyrDialog):
layout.addStretch() layout.addStretch()
def setup_label(self):
self._label = self.find(QLabel, "label_4")
self._label.setFrameStyle(QFrame.StyledPanel)
self._label.setStyleSheet('background-color: white')
self.set_label()
for r in self._radio:
r[1].clicked.connect(self.set_label)
def set_label(self):
if self._radio[0][1].isChecked():
self._label.setText(self._parent.text_bief() + "\n" +
self._parent.text_time())
else:
self._label.setText(self._parent.text_bief() + "\n" +
self._parent.text_profile())
def setup_envelop_box(self): def setup_envelop_box(self):
layout = self.find(QVBoxLayout, "verticalLayout_x") layout = self.find(QVBoxLayout, "verticalLayout_x")
self._envelop = QCheckBox( self._envelop = QCheckBox(

View File

@ -19,7 +19,7 @@
from View.Tools.PamhyrWindow import PamhyrDialog from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QRadioButton, QCheckBox, QVBoxLayout, QRadioButton, QCheckBox, QVBoxLayout, QLabel, QFrame
) )
from View.Results.translate import ResultsTranslate from View.Results.translate import ResultsTranslate
@ -50,6 +50,7 @@ class CustomExportAdisDialog(PamhyrDialog):
self.setup_radio_buttons_x() self.setup_radio_buttons_x()
self.setup_radio_buttons_pol() self.setup_radio_buttons_pol()
self.setup_label()
self.setup_check_boxes() self.setup_check_boxes()
self.value = None self.value = None
@ -84,6 +85,22 @@ class CustomExportAdisDialog(PamhyrDialog):
self._radio2[0][1].setChecked(True) self._radio2[0][1].setChecked(True)
layout.addStretch() layout.addStretch()
def setup_label(self):
self._label = self.find(QLabel, "label_4")
self._label.setFrameStyle(QFrame.StyledPanel)
self._label.setStyleSheet('background-color: white')
self.set_label()
for r in self._radio:
r[1].clicked.connect(self.set_label)
def set_label(self):
if self._radio[0][1].isChecked():
self._label.setText(self._parent.text_bief() + "\n" +
self._parent.text_time())
else:
self._label.setText(self._parent.text_bief() + "\n" +
self._parent.text_profile())
def setup_check_boxes(self): def setup_check_boxes(self):
self._check = [] self._check = []
layout = self.find(QVBoxLayout, "verticalLayout_y") layout = self.find(QVBoxLayout, "verticalLayout_y")

View File

@ -19,7 +19,7 @@
from View.Tools.PamhyrWindow import PamhyrDialog from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QRadioButton, QCheckBox, QVBoxLayout, QRadioButton, QCheckBox, QVBoxLayout, QLabel, QFrame
) )
from View.Results.CustomPlot.Translate import CustomPlotTranslate from View.Results.CustomPlot.Translate import CustomPlotTranslate
@ -38,10 +38,12 @@ class CustomPlotValuesSelectionDialog(PamhyrDialog):
parent=parent parent=parent
) )
self._parent = parent
self._available_values_x = self._trad.get_dict("values_x") self._available_values_x = self._trad.get_dict("values_x")
self._available_values_y = self._trad.get_dict("values_y") self._available_values_y = self._trad.get_dict("values_y")
self.setup_radio_buttons() self.setup_radio_buttons()
self.setup_label()
self.setup_envelop_box() self.setup_envelop_box()
self.setup_check_boxs() self.setup_check_boxs()
@ -62,6 +64,22 @@ class CustomPlotValuesSelectionDialog(PamhyrDialog):
self._radio[0][1].setChecked(True) self._radio[0][1].setChecked(True)
layout.addStretch() layout.addStretch()
def setup_label(self):
self._label = self.find(QLabel, "label_3")
self._label.setFrameStyle(QFrame.StyledPanel)
self._label.setStyleSheet('background-color: white')
self.set_label()
for r in self._radio:
r[1].clicked.connect(self.set_label)
def set_label(self):
if self._radio[0][1].isChecked():
self._label.setText(self._parent.text_bief() + "\n" +
self._parent.text_time())
else:
self._label.setText(self._parent.text_bief() + "\n" +
self._parent.text_profile())
def setup_envelop_box(self): def setup_envelop_box(self):
self._envelop = [] self._envelop = []
layout = self.find(QVBoxLayout, "verticalLayout_x") layout = self.find(QVBoxLayout, "verticalLayout_x")

View File

@ -204,7 +204,8 @@ class CustomPlot(PamhyrPlot):
e = list( e = list(
map( map(
lambda p: max(self.get_ts_zmin(p, res_id)), lambda p: max(self.get_ts_zmin(
p, self._current_res_id)),
range(len(reach)) range(len(reach))
) )
) )
@ -217,7 +218,8 @@ class CustomPlot(PamhyrPlot):
e = list( e = list(
map( map(
lambda p: min(self.get_ts_zmin(p, res_id)), lambda p: min(self.get_ts_zmin(
p, self._current_res_id)),
range(len(reach)) range(len(reach))
) )
) )

View File

@ -21,7 +21,7 @@ import logging
from functools import reduce from functools import reduce
from datetime import datetime from datetime import datetime
from tools import timer, trace from tools import timer, trace, logger_exception
from View.Tools.PamhyrPlot import PamhyrPlot from View.Tools.PamhyrPlot import PamhyrPlot
from PyQt5.QtCore import ( from PyQt5.QtCore import (
@ -68,6 +68,7 @@ class PlotH(PamhyrPlot):
self._line_max = [] self._line_max = []
self._line = [] self._line = []
self._add_data_lines = []
@property @property
def results(self): def results(self):
@ -117,15 +118,17 @@ class PlotH(PamhyrPlot):
self.set_ticks_time_formater() self.set_ticks_time_formater()
self.draw_additional_data(0)
self.enable_legend() self.enable_legend()
self.canvas.draw_idle() self.canvas.draw_idle()
self.update_idle self.update_idle()
self.draw_current() self.draw_current()
self._init = True self._init = True
def draw_data(self, res_id): def draw_data(self, res_id):
results = self.results[res_id] results = self.results[res_id]
reach = results.river.reach(self._current_reach_id) reach = results.river.reach(self._current_reach_id)
for i, p in enumerate(self._current_profile_id): for i, p in enumerate(self._current_profile_id):
@ -152,6 +155,28 @@ class PlotH(PamhyrPlot):
) )
self._line.append(line) self._line.append(line)
def draw_additional_data(self, res_id):
results = self.results[res_id]
self._add_data_lines = []
for data in results.get("additional_data"):
data = data._data
x, y = data['x'], data['y']
legend = data['legend']
unit = data['unit']
if data['type_x'] == 'time' and data['type_y'] == 'discharge':
line, = self.canvas.axes.plot(
x, y, marker="+",
label=legend + ' ' + unit
)
self._add_data_lines.append(line)
self.enable_legend()
self.canvas.draw_idle()
def draw_current(self): def draw_current(self):
self._current, = self.canvas.axes.plot( self._current, = self.canvas.axes.plot(
[self._current_timestamp, self._current_timestamp], [self._current_timestamp, self._current_timestamp],
@ -220,6 +245,10 @@ class PlotH(PamhyrPlot):
self.update_current() self.update_current()
self.update_idle() self.update_idle()
def update_additional_data(self):
self.draw_additional_data(0)
self.update_idle()
def update_all(self): def update_all(self):
self._current_reach_id = self._parent._get_current_reach() self._current_reach_id = self._parent._get_current_reach()
self._current_profile_id = self._parent._get_current_profiles_list() self._current_profile_id = self._parent._get_current_profiles_list()

View File

@ -210,6 +210,29 @@ class PlotRKC(PamhyrPlot):
linestyle='dotted', linestyle='dotted',
) )
def draw_additional_data(self, res_id):
results = self.results[res_id]
self._add_data_lines = []
for data in results.get("additional_data"):
data = data._data
tx, ty = data['type_x'], data['type_y']
x, y = data['x'], data['y']
legend = data['legend']
unit = data['unit']
if tx == 'water_elevation' and ty == 'time':
line, = self.canvas.axes.plot(
x, y, marker="+",
label=legend + ' ' + unit
)
self._add_data_lines.append(line)
self.canvas.draw_idle()
def draw_current(self, reach): def draw_current(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()
@ -332,6 +355,10 @@ class PlotRKC(PamhyrPlot):
alpha=0.7, interpolate=True alpha=0.7, interpolate=True
) )
def update_additional_data(self):
self.draw_additional_data(0)
self.update_idle()
def update_current(self): def update_current(self):
results = self.results[self._current_res_id] results = self.results[self._current_res_id]
reach = results.river.reach(self._current_reach_id) reach = results.river.reach(self._current_reach_id)

View File

@ -20,7 +20,7 @@ import logging
from functools import reduce from functools import reduce
from tools import timer, trace from tools import timer, trace, logger_exception
from View.Tools.PamhyrPlot import PamhyrPlot from View.Tools.PamhyrPlot import PamhyrPlot
import numpy as np import numpy as np
from matplotlib import collections from matplotlib import collections
@ -68,6 +68,9 @@ class PlotXY(PamhyrPlot):
self._plot_img = {} self._plot_img = {}
self._geotiff_img = []
self._geotiff_bounds = []
self._parent = parent self._parent = parent
self._timestamps = parent._timestamps self._timestamps = parent._timestamps
self._current_timestamp = max(self._timestamps) self._current_timestamp = max(self._timestamps)
@ -203,7 +206,6 @@ class PlotXY(PamhyrPlot):
self.canvas.axes.add_collection(self.line_xy_collection) self.canvas.axes.add_collection(self.line_xy_collection)
def draw_other_profiles(self, reaches): def draw_other_profiles(self, reaches):
for reach in reaches: for reach in reaches:
for xy in zip(reach.geometry.get_x(), for xy in zip(reach.geometry.get_x(),
reach.geometry.get_y()): reach.geometry.get_y()):
@ -325,6 +327,24 @@ class PlotXY(PamhyrPlot):
alpha=0.7 alpha=0.7
) )
def add_geotiff(self, img, bounds):
self._geotiff_img.append(img)
self._geotiff_bounds.append(bounds)
def draw_add_geotiff(self):
xlim = self.canvas.axes.get_xlim()
ylim = self.canvas.axes.get_ylim()
for i, img in enumerate(self._geotiff_img):
bounds = self._geotiff_bounds[i]
self.canvas.axes.imshow(img.transpose((1, 2, 0)),
extent=bounds)
self.idle()
self.canvas.axes.set_xlim(xlim)
self.canvas.axes.set_ylim(ylim)
def draw_geotiff(self): def draw_geotiff(self):
if not _rasterio_loaded: if not _rasterio_loaded:
return return
@ -332,7 +352,10 @@ class PlotXY(PamhyrPlot):
lst = self._data[0]._study.river._geotiff.lst lst = self._data[0]._study.river._geotiff.lst
for img in self._plot_img: for img in self._plot_img:
self._plot_img[img].remove() try:
self._plot_img[img].remove()
except Exception as e:
logger_exception(e)
self._plot_img = {} self._plot_img = {}
@ -358,6 +381,7 @@ class PlotXY(PamhyrPlot):
if not geotiff.is_enabled(): if not geotiff.is_enabled():
self._plot_img[geotiff].set(alpha=0.5) self._plot_img[geotiff].set(alpha=0.5)
self.draw_add_geotiff()
self.idle() self.idle()
def set_reach(self, reach_id): def set_reach(self, reach_id):
@ -453,8 +477,12 @@ class PlotXY(PamhyrPlot):
overflow.append(pt_right) overflow.append(pt_right)
for plot in self.overflow: for plot in self.overflow:
plot[0].remove() try:
plot[0].remove()
except Exception as e:
logger_exception(e)
del plot[0] del plot[0]
self.overflow = [] self.overflow = []
for p in overflow: for p in overflow:

View File

@ -314,16 +314,12 @@ class ResultsWindow(PamhyrWindow):
super(ResultsWindow, self).closeEvent(event) super(ResultsWindow, self).closeEvent(event)
def _compute_status_label(self): def _compute_status_label(self):
# Timestamp
ts = self._timestamps[self._slider_time.value()]
t0 = datetime.fromtimestamp(0) return (self.text_bief() + " | " +
fts = str( self.text_profile() + " | " +
datetime.fromtimestamp(ts) - t0 self.text_time())
)
fts.replace("days", _translate("Results", "days"))\
.replace("day", _translate("Results", "day"))
def text_bief(self):
# Reach # Reach
table = self.find(QTableView, f"tableView_reach") table = self.find(QTableView, f"tableView_reach")
indexes = table.selectedIndexes() indexes = table.selectedIndexes()
@ -331,7 +327,16 @@ class ResultsWindow(PamhyrWindow):
reach = self._study.river.enable_edges()[0] reach = self._study.river.enable_edges()[0]
else: else:
reach = self._study.river.enable_edges()[indexes[0].row()] reach = self._study.river.enable_edges()[indexes[0].row()]
return f"{self._trad['reach']}: {reach.name}"
def text_profile(self):
# Reach
table = self.find(QTableView, f"tableView_reach")
indexes = table.selectedIndexes()
if len(indexes) == 0:
reach = self._study.river.enable_edges()[0]
else:
reach = self._study.river.enable_edges()[indexes[0].row()]
# Profile # Profile
table = self.find(QTableView, f"tableView_profile") table = self.find(QTableView, f"tableView_profile")
indexes = table.selectedIndexes() indexes = table.selectedIndexes()
@ -341,10 +346,22 @@ class ResultsWindow(PamhyrWindow):
profile = reach.reach.profile(indexes[0].row()) profile = reach.reach.profile(indexes[0].row())
pname = profile.name if profile.name != "" else profile.rk pname = profile.name if profile.name != "" else profile.rk
return f"{self._trad['cross_section']}: {pname}"
return (f"{self._trad['reach']}: {reach.name} | " + def text_time(self):
f"{self._trad['cross_section']}: {pname} | " + # Timestamp
f"{self._trad['unit_time_s']} : {fts} ({ts} sec)") ts = self._timestamps[self._slider_time.value()]
t0 = datetime.fromtimestamp(0)
fts = str(
datetime.fromtimestamp(ts) - t0
)
fts = str(
datetime.fromtimestamp(ts) - t0
)
fts.replace("days", _translate("Results", "days"))\
.replace("day", _translate("Results", "day"))
return f"{self._trad['time']} : {fts} ({ts} sec)"
def setup_statusbar(self): def setup_statusbar(self):
txt = self._compute_status_label() txt = self._compute_status_label()
@ -779,20 +796,29 @@ class ResultsWindow(PamhyrWindow):
first_line.append(f"Profile: {pname}") first_line.append(f"Profile: {pname}")
val_dict = self._export_time(profile_id, y, solver_id) val_dict = self._export_time(profile_id, y, solver_id)
with open(filename, 'w', newline='') as csvfile: try:
writer = csv.writer(csvfile, delimiter=',', with open(filename, 'w', newline='') as csvfile:
quotechar='|', quoting=csv.QUOTE_MINIMAL) writer = csv.writer(csvfile, delimiter=',',
dict_x = self._trad.get_dict("values_x") quotechar='|', quoting=csv.QUOTE_MINIMAL)
header = [] dict_x = self._trad.get_dict("values_x")
writer.writerow(first_line) header = []
for text in val_dict.keys(): writer.writerow(first_line)
header.append(text) for text in val_dict.keys():
writer.writerow(header) header.append(text)
for row in range(len(val_dict[dict_x[x]])): writer.writerow(header)
line = [] for row in range(len(val_dict[dict_x[x]])):
for var in val_dict.keys(): line = []
line.append(val_dict[var][row]) for var in val_dict.keys():
writer.writerow(line) line.append(val_dict[var][row])
writer.writerow(line)
self._timer.stop()
except Exception as e:
self.message_box(
window_title=self._trad["Warning"],
text=self._trad["mb_write_error"],
informative_text=self._trad["mb_close_file"]
)
logger_exception(e)
def export_all(self, reach, directory, timestamps): def export_all(self, reach, directory, timestamps):
name = reach.name name = reach.name
@ -805,17 +831,25 @@ class ResultsWindow(PamhyrWindow):
f"reach_{name}.csv" f"reach_{name}.csv"
) )
with open(file_name, 'w', newline='') as csvfile: try:
writer = csv.writer(csvfile, delimiter=',', with open(file_name, 'w', newline='') as csvfile:
quotechar='|', quoting=csv.QUOTE_MINIMAL) writer = csv.writer(csvfile, delimiter=',',
ts = timestamps[0] quotechar='|', quoting=csv.QUOTE_MINIMAL)
writer.writerow(self._table["raw_data"]._headers) ts = timestamps[0]
for row in range(self._table["raw_data"].rowCount()): writer.writerow(self._table["raw_data"]._headers)
line = [] for row in range(self._table["raw_data"].rowCount()):
for column in range(self._table["raw_data"].columnCount()): line = []
index = self._table["raw_data"].index(row, column) for column in range(self._table["raw_data"].columnCount()):
line.append(self._table["raw_data"].data(index)) index = self._table["raw_data"].index(row, column)
writer.writerow(line) line.append(self._table["raw_data"].data(index))
writer.writerow(line)
except Exception as e:
self.message_box(
window_title=self._trad["Warning"],
text=self._trad["mb_write_errore"],
informative_text=self._trad["mb_close_file"]
)
logger_exception(e)
def export_current(self): def export_current(self):
self.file_dialog( self.file_dialog(
@ -1250,24 +1284,22 @@ class ResultsWindow(PamhyrWindow):
# b[1] bottom # b[1] bottom
# b[2] right # b[2] right
# b[3] top # b[3] top
xlim = self.canvas.axes.get_xlim() bounds = [b[0], b[2], b[1], b[3]]
ylim = self.canvas.axes.get_ylim()
if b[2] > b[0] and b[1] < b[3]: if not (b[2] > b[0] and b[1] < b[3]):
self.canvas.axes.imshow(img.transpose((1, 2, 0)), xlim = self.canvas.axes.get_xlim()
extent=[b[0], b[2], b[1], b[3]]) ylim = self.canvas.axes.get_ylim()
else:
dlg = CoordinatesDialog( dlg = CoordinatesDialog(
xlim, ylim, xlim, ylim,
trad=self._trad, trad=self._trad,
parent=self parent=self
) )
if dlg.exec(): if dlg.exec():
self.canvas.axes.imshow(img.transpose((1, 2, 0)), bounds = dlg.values
extent=dlg.values)
self.plot_xy.idle() self.plot_xy.add_geotiff(img, bounds)
self.canvas.axes.set_xlim(xlim) self.plot_xy.draw_add_geotiff()
self.canvas.axes.set_ylim(ylim)
return
def import_data(self): def import_data(self):
file_types = [ file_types = [
@ -1289,6 +1321,8 @@ class ResultsWindow(PamhyrWindow):
x, y = self.read_csv_file_data(filename) x, y = self.read_csv_file_data(filename)
data = self.read_csv_file_format(x, y) data = self.read_csv_file_format(x, y)
if data is None:
return
results = self._results[self._current_results[0]] results = self._results[self._current_results[0]]
data_lst = results.get("additional_data") data_lst = results.get("additional_data")
@ -1362,32 +1396,9 @@ class ResultsWindow(PamhyrWindow):
def update_plot_additional_data(self): def update_plot_additional_data(self):
results = self._results[self._current_results[0]] results = self._results[self._current_results[0]]
self.plot_rkc.update_additional_data()
self.plot_h.update_additional_data()
for data in results.get("additional_data"): for data in results.get("additional_data"):
data = data._data
x, y = data['x'], data['y']
legend = data['legend']
unit = data['unit']
if (
data['type_x'] == 'water_elevation' and
data['type_y'] == 'time'
):
line = self.canvas_2.axes.plot(
x, y, marker="+",
label=legend + ' ' + unit
)
self.plot_rkc.canvas.draw_idle()
self.plot_rkc.update_idle()
if data['type_x'] == 'time' and data['type_y'] == 'discharge':
line = self.canvas_4.axes.plot(
x, y, marker="+",
label=legend + ' ' + unit
)
self.plot_h._line.append(line)
self.plot_h.enable_legend()
self.plot_h.canvas.draw_idle()
self.plot_h.update_idle()
for p in self._additional_plot: for p in self._additional_plot:
self._additional_plot[p].add_imported_plot(data) self._additional_plot[p].add_imported_plot(data)

View File

@ -345,24 +345,29 @@ class ResultsWindowAdisTS(PamhyrWindow):
super(ResultsWindowAdisTS, self).closeEvent(event) super(ResultsWindowAdisTS, self).closeEvent(event)
def _compute_status_label(self): def _compute_status_label(self):
# Timestamp return (self.text_bief() + " | " +
ts = self._timestamps[self._slider_time.value()] self.text_profile() + " | " +
self.text_pollutant() + " | " +
t0 = datetime.fromtimestamp(0) self.text_time())
fts = str(
datetime.fromtimestamp(ts) - t0
)
fts.replace("days", _translate("Results", "days"))\
.replace("day", _translate("Results", "day"))
def text_bief(self):
# Reach # Reach
table = self.find(QTableView, f"tableView_reach") table = self.find(QTableView, f"tableView_reach")
indexes = table.selectedIndexes() indexes = table.selectedIndexes()
if len(indexes) == 0: if len(indexes) == 0:
reach = self._study.river.edges()[0] reach = self._study.river.enable_edges()[0]
else: else:
reach = self._study.river.edges()[indexes[0].row()] reach = self._study.river.enable_edges()[indexes[0].row()]
return f"{self._trad['reach']}: {reach.name}"
def text_profile(self):
# Reach
table = self.find(QTableView, f"tableView_reach")
indexes = table.selectedIndexes()
if len(indexes) == 0:
reach = self._study.river.enable_edges()[0]
else:
reach = self._study.river.enable_edges()[indexes[0].row()]
# Profile # Profile
table = self.find(QTableView, f"tableView_profile") table = self.find(QTableView, f"tableView_profile")
indexes = table.selectedIndexes() indexes = table.selectedIndexes()
@ -372,7 +377,24 @@ class ResultsWindowAdisTS(PamhyrWindow):
profile = reach.reach.profile(indexes[0].row()) profile = reach.reach.profile(indexes[0].row())
pname = profile.name if profile.name != "" else profile.rk pname = profile.name if profile.name != "" else profile.rk
return f"{self._trad['cross_section']}: {pname}"
def text_time(self):
# Timestamp
ts = self._timestamps[self._slider_time.value()]
t0 = datetime.fromtimestamp(0)
fts = str(
datetime.fromtimestamp(ts) - t0
)
fts = str(
datetime.fromtimestamp(ts) - t0
)
fts.replace("days", _translate("Results", "days"))\
.replace("day", _translate("Results", "day"))
return f"{self._trad['time']} : {fts} ({ts} sec)"
def text_pollutant(self):
# Pollutant # Pollutant
table = self.find(QTableView, f"tableView_pollutants") table = self.find(QTableView, f"tableView_pollutants")
indexes = table.selectedIndexes() indexes = table.selectedIndexes()
@ -381,10 +403,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
self._results.pollutants_list[i.row()+1] for i in indexes self._results.pollutants_list[i.row()+1] for i in indexes
] ]
return (f"{self._trad['reach']}: {reach.name} | " + return (f"Pollutant: {', '.join(self.pollutant_label)}")
f"{self._trad['cross_section']}: {pname} | " +
f"Pollutant: {', '.join(self.pollutant_label)} | " +
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()

View File

@ -56,6 +56,13 @@ class ResultsTranslate(MainTranslate):
self._dict["ImageCoordinates"] = _translate( self._dict["ImageCoordinates"] = _translate(
"Results", "Image coordinates" "Results", "Image coordinates"
) )
self._dict["mb_write_error"] = _translate(
"Results", "An error occured when writing to file"
)
self._dict["mb_close_file"] = _translate(
"Results",
"If the file is in use, close it and try again"
)
self._sub_dict["table_headers_reach"] = { self._sub_dict["table_headers_reach"] = {
"name": _translate("Results", "Reach name"), "name": _translate("Results", "Reach name"),

View File

@ -94,7 +94,8 @@ class SelectSolverWindowAdisTS(PamhyrDialog):
) )
solvers_mage = list(filter( solvers_mage = list(filter(
lambda x: "mage" in x._type.lower(), self._config.solvers lambda x: "mage" or "rubar" in x._type.lower(),
self._config.solvers
)) ))
solvers_mage_names = list(map(lambda x: x._name, solvers_mage)) solvers_mage_names = list(map(lambda x: x._name, solvers_mage))
@ -184,6 +185,9 @@ class SolverLogWindowAdisTS(PamhyrWindow):
parent=parent parent=parent
) )
self._workdir = ""
self._workdir_mage = ""
self.setup_action() self.setup_action()
self.setup_alarm() self.setup_alarm()
self.setup_connections() self.setup_connections()
@ -226,17 +230,47 @@ class SolverLogWindowAdisTS(PamhyrWindow):
self._alarm.timeout.connect(self.update) self._alarm.timeout.connect(self.update)
def setup_workdir(self): def setup_workdir(self):
self._workdir = "" scenario = self._study.status.scenario
srep = scenario.workdir()
if self._study.filename == "": if self._study.filename == "":
self._workdir = tempfile.TemporaryDirectory() self._workdir = os.path.join(
tempfile.TemporaryDirectory(),
srep
)
else: else:
self._workdir = os.path.join( self._workdir = os.path.join(
os.path.dirname(self._study.filename), os.path.dirname(self._study.filename),
"_PAMHYR_", "_PAMHYR_",
self._study.name.replace(" ", "_"), self._study.name.replace(" ", "_"),
self._solver.name.replace(" ", "_"), self._solver.name.replace(" ", "_"),
srep
) )
os.makedirs(self._workdir, exist_ok=True)
logger.info(f"Create workdir: '{self._workdir}'")
os.makedirs(self._workdir, exist_ok=True)
self.setup_mage_workdir()
def setup_mage_workdir(self):
scenario = self._study.status.scenario
srep = scenario.workdir()
if self._study.filename == "":
self._workdir_mage = os.path.join(
tempfile.TemporaryDirectory(),
srep
)
else:
self._workdir_mage = os.path.join(
os.path.dirname(self._study.filename),
"_PAMHYR_",
self._study.name.replace(" ", "_"),
self._mage_rep.replace(" ", "_"),
srep
)
logger.info(f"Create workdir: '{self._workdir_mage}'")
def setup_process(self): def setup_process(self):
self._alarm.start(100) self._alarm.start(100)
@ -252,7 +286,8 @@ class SolverLogWindowAdisTS(PamhyrWindow):
def export(self): def export(self):
self._log(f" *** Export study {self._solver.name}", color="blue") self._log(f" *** Export study {self._solver.name}", color="blue")
ok = self._solver.export( ok = self._solver.export(
self._study, self._workdir, self._mage_rep, qlog=self._output self._study, self._workdir, self._workdir_mage,
qlog=self._output
) )
self.update() self.update()
@ -366,7 +401,8 @@ class SolverLogWindowAdisTS(PamhyrWindow):
self._log(f" *** Export study {self._solver.name}", color="blue") self._log(f" *** Export study {self._solver.name}", color="blue")
ok = self._solver.export( ok = self._solver.export(
self._study, self._workdir, self._mage_rep, qlog=self._output self._study, self._workdir, self._workdir_mage,
qlog=self._output
) )
if not ok: if not ok:
@ -442,12 +478,7 @@ class SolverLogWindowAdisTS(PamhyrWindow):
mage_solver = next(filter( mage_solver = next(filter(
lambda x: x._name == self._mage_rep, self._config.solvers lambda x: x._name == self._mage_rep, self._config.solvers
)) ))
workdir_mage = os.path.join( workdir_mage = self._workdir_mage
os.path.dirname(self._study.filename),
"_PAMHYR_",
self._study.name.replace(" ", "_"),
mage_solver.name.replace(" ", "_"),
)
def reading_fn(): def reading_fn():
self._results_mage = mage_solver.results( self._results_mage = mage_solver.results(

View File

@ -53,10 +53,10 @@ class ParamTranslate(MainTranslate):
self._sub_dict["names"] = { self._sub_dict["names"] = {
"all_init_time": "all_init_time":
_translate("SolverParameters", _translate("SolverParameters",
"Initial time (jj:hh:mm:ss)"), "Initial time (jjj:hh:mm:ss)"),
"all_final_time": "all_final_time":
_translate("SolverParameters", _translate("SolverParameters",
"Final time (jj:hh:mm:ss)"), "Final time (jjj:hh:mm:ss)"),
"all_timestep": "all_timestep":
_translate("SolverParameters", _translate("SolverParameters",
"Timestep (second)"), "Timestep (second)"),

View File

@ -91,6 +91,7 @@ class WaitingDialog(PamhyrDialog):
parent=parent parent=parent
) )
self._to_close = False self._to_close = False
self.setFixedSize(self.width(), self.height())
self._payload_fn = payload_fn self._payload_fn = payload_fn

View File

@ -7,23 +7,13 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>194</width> <width>194</width>
<height>70</height> <height>126</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Dialog</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QSplitter" name="splitter"> <widget class="QSplitter" name="splitter">
<property name="orientation"> <property name="orientation">
@ -64,6 +54,23 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -7,14 +7,24 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>414</width> <width>414</width>
<height>70</height> <height>132</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Dialog</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="3" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSplitter" name="splitter"> <widget class="QSplitter" name="splitter">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -43,13 +53,10 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QLabel" name="label_3">
<property name="orientation"> <property name="text">
<enum>Qt::Horizontal</enum> <string>TextLabel</string>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -22,7 +22,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Upstream height (m)</string> <string>Upstream elevation (m)</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -70,7 +70,7 @@
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Downstream height (m)</string> <string>Downstream elevation (m)</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -101,6 +101,7 @@ class Config(SQL):
# Add default solver # Add default solver
posix = os.name == 'posix' posix = os.name == 'posix'
ext = "" if posix else ".exe" ext = "" if posix else ".exe"
path = os.path.join("@install_dir", "mage8", f"mage{ext}")
self.execute(f""" self.execute(f"""
INSERT INTO solver VALUES ( INSERT INTO solver VALUES (
@ -111,7 +112,7 @@ class Config(SQL):
'', '', '', '', '', '',
'', '',
'@install_dir/mage/mage{ext} @args @input', '{path} @args @input',
'' ''
) )
""") """)
@ -135,16 +136,19 @@ class Config(SQL):
if int(release) < 5: if int(release) < 5:
posix = os.name == 'posix' posix = os.name == 'posix'
ext = "" if posix else ".exe" ext = "" if posix else ".exe"
path = os.path.join("@install_dir", "mage8", f"mage{ext}")
self.execute( self.execute(
"UPDATE solver SET cmd_solver=" + "UPDATE solver SET cmd_solver=" +
f"'@install_dir/mage8/mage{ext} @args @input' " f"'{path} @args @input' "
"WHERE name='default-mage'" "WHERE name='default-mage'"
) )
if int(release) < 6: if int(release) < 6:
posix = os.name == 'posix' posix = os.name == 'posix'
ext = "" if posix else ".exe" ext = "" if posix else ".exe"
path = os.path.join("@install_dir",
"adists", f"adists{ext}")
self.execute(f""" self.execute(f"""
INSERT INTO solver VALUES ( INSERT INTO solver VALUES (
@ -155,19 +159,21 @@ class Config(SQL):
'', '', '', '', '', '',
'', '',
'@install_dir/adists/adists{ext} @args @input', '{path} @args @input',
'' ''
) )
""") """)
self.execute( self.execute(
"UPDATE solver SET cmd_solver=" + "UPDATE solver SET cmd_solver=" +
f"'@install_dir/adists/adists{ext} @args @input' " f"'{path} @args @input' "
"WHERE name='default-AdisTS'" "WHERE name='default-AdisTS'"
) )
if int(release) < 7: if int(release) < 7:
posix = os.name == 'posix' posix = os.name == 'posix'
ext = "" if posix else ".exe" ext = "" if posix else ".exe"
path = os.path.join("@install_dir",
"rubar", f"rubarbe{ext}")
self.execute(f""" self.execute(f"""
INSERT INTO solver VALUES ( INSERT INTO solver VALUES (
@ -178,13 +184,13 @@ class Config(SQL):
'', '', '', '', '', '',
'', '',
'@install_dir/rubar/rubar3{ext} @args @input', '{path} @args @input',
'' ''
) )
""") """)
self.execute( self.execute(
"UPDATE solver SET cmd_solver=" + "UPDATE solver SET cmd_solver=" +
f"'@install_dir/rubar/rubar3{ext} @args @input' " f"'{path} @args @input' "
"WHERE name='default-Rubar3'" "WHERE name='default-Rubar3'"
) )
@ -350,14 +356,24 @@ class Config(SQL):
ctor = solver_type_list["mage8"] ctor = solver_type_list["mage8"]
new = ctor("default-mage") new = ctor("default-mage")
new._description = "Default Pamhyr2 mage 8 version" new._description = "Default Pamhyr2 mage 8 version"
new._cmd_solver = f""""@install_dir/mage8/mage{ext}" @args @input""" path = os.path.join("@install_dir", "mage8", "mage")
new._cmd_solver = f""""{path}{ext}" @args @input"""
self._solvers.append(new) self._solvers.append(new)
# AdisTS # AdisTS
ctor = solver_type_list["adistswc"] ctor = solver_type_list["adistswc"]
new = ctor("default-AdisTS") new = ctor("default-AdisTS")
new._description = "Default Pamhyr2 AdisTS version" new._description = "Default Pamhyr2 AdisTS version"
new._cmd_solver = f""""@install_dir/adists/adists{ext}" @args @input""" path = os.path.join("@install_dir", "adists", "adists")
new._cmd_solver = f""""{path}{ext}" @args @input"""
self._solvers.append(new)
# Rubar3
ctor = solver_type_list["rubar3"]
new = ctor("default-Rubar3")
new._description = "Default Pamhyr2 Rubar 3 version"
path = os.path.join("@install_dir", "rubar", f"rubarbe{ext}")
new._cmd_solver = f""""{path}" @args @input"""
self._solvers.append(new) self._solvers.append(new)
# Rubar3 # Rubar3

View File

@ -3785,13 +3785,13 @@ Cette fonctionnalité nécessite un bief muni d'une géométrie.</translation>
</message> </message>
<message> <message>
<location filename="../View/SolverParameters/translate.py" line="55"/> <location filename="../View/SolverParameters/translate.py" line="55"/>
<source>Initial time (jj:hh:mm:ss)</source> <source>Initial time (jjj:hh:mm:ss)</source>
<translation>Temps initial (jj:hh:mm:ss)</translation> <translation>Temps initial (jjj:hh:mm:ss)</translation>
</message> </message>
<message> <message>
<location filename="../View/SolverParameters/translate.py" line="58"/> <location filename="../View/SolverParameters/translate.py" line="58"/>
<source>Final time (jj:hh:mm:ss)</source> <source>Final time (jjj:hh:mm:ss)</source>
<translation>Temps final (jj:hh:mm:ss)</translation> <translation>Temps final (jjj:hh:mm:ss)</translation>
</message> </message>
<message> <message>
<location filename="../View/SolverParameters/translate.py" line="61"/> <location filename="../View/SolverParameters/translate.py" line="61"/>