HS: Use section ID instead of RK.

scenarios
Pierre-Antoine Rouby 2024-08-21 11:31:13 +02:00
parent 6225f8940e
commit 7f87d22249
7 changed files with 176 additions and 60 deletions

View File

@ -335,6 +335,9 @@ class ProfileXYZ(Profile, SQLSubModel):
return point
def display_name(self):
return f"{self.name} ({self.rk:.4f})"
def x(self):
return [point.x for point in self.points]

View File

@ -46,8 +46,8 @@ class HydraulicStructure(SQLSubModel):
self._status = status
self._name = name
self._input_rk = None
self._output_rk = None
self._input_section = None
self._output_section = None
self._input_reach = None
self._output_reach = None
self._enabled = True
@ -60,14 +60,18 @@ class HydraulicStructure(SQLSubModel):
{cls.create_db_add_pamhyr_id()},
name TEXT NOT NULL,
enabled BOOLEAN NOT NULL,
input_rk REAL NOT NULL,
output_rk REAL NOT NULL,
input_reach INTEGER,
output_reach INTEGER,
input_section INTEGER,
output_section INTEGER,
{Scenario.create_db_add_scenario()},
{Scenario.create_db_add_scenario_fk()},
FOREIGN KEY(input_reach) REFERENCES river_reach(pamhyr_id),
FOREIGN KEY(output_reach) REFERENCES river_reach(pamhyr_id),
FOREIGN KEY(input_section)
REFERENCES geometry_profileXYZ(pamhyr_id),
FOREIGN KEY(output_section)
REFERENCES geometry_profileXYZ(pamhyr_id),
PRIMARY KEY(pamhyr_id, scenario)
)
""")
@ -98,13 +102,38 @@ class HydraulicStructure(SQLSubModel):
cls._db_update_to_0_1_0(execute, data)
if major == "0" and minor == "1":
if int(release) < 1:
cls._db_update_to_0_1_1(execute, data)
return cls._update_submodel(execute, version, data)
@classmethod
def _db_update_to_0_1_1(cls, execute, data,
origin_version="0.1.0"):
for v in ["input", "output"]:
execute(
"ALTER TABLE hydraulic_structures " +
f"ADD COLUMN {v}_section INTEGER"
)
cls._db_update_to_0_1_1_assoc_section_from_rk(
execute, "hydraulic_structures",
reach_column=f"{v}_reach",
rk_column=f"{v}_rk",
section_column=f"{v}_section",
origin_version=origin_version
)
@classmethod
def _db_update_to_0_1_0(cls, execute, data):
table = "hydraulic_structures"
reachs = data['id2pid']['river_reach']
cls._db_update_to_0_1_1(
execute, data,
origin_version="0.0.*"
)
cls.update_db_add_pamhyr_id(execute, table, data)
Scenario.update_db_add_scenario(execute, table)
@ -112,9 +141,9 @@ class HydraulicStructure(SQLSubModel):
execute(
f"INSERT INTO {table}_tmp " +
"(pamhyr_id, name, enabled, input_rk, output_rk, " +
"(pamhyr_id, name, enabled, input_section, output_section, " +
"input_reach, output_reach, scenario) " +
"SELECT pamhyr_id, name, enabled, input_rk, output_rk, " +
"SELECT pamhyr_id, name, enabled, input_section, output_section, " +
"input_reach, output_reach, scenario " +
f"FROM {table}"
)
@ -155,7 +184,7 @@ class HydraulicStructure(SQLSubModel):
table = execute(
"SELECT pamhyr_id, name, enabled, " +
"input_rk, output_rk, " +
"input_section, output_section, " +
"input_reach, output_reach " +
"FROM hydraulic_structures"
)
@ -166,29 +195,44 @@ class HydraulicStructure(SQLSubModel):
hs_id = next(it)
name = next(it)
enabled = (next(it) == 1)
input_rk = next(it)
output_rk = next(it)
input_section_id = next(it)
input_section_id = (
-1 if input_section_id is None else input_section_id
)
output_section_id = next(it)
output_section_id = (
-1 if output_section_id is None else output_section_id
)
input_reach_id = next(it)
output_reach_id = next(it)
hs = cls(
id=hs_id,
name=name,
status=data['status']
id=hs_id, name=name, status=data['status']
)
hs.enabled = enabled
hs.input_rk = input_rk if input_rk != -1 else None
hs.output_rk = output_rk if output_rk != -1 else None
hs.input_reach, hs.output_reach = reduce(
lambda acc, n: (
n if n.id == input_reach_id else acc[0],
n if n.id == output_reach_id else acc[1]
n if n.pamhyr_id == input_reach_id else acc[0],
n if n.pamhyr_id == output_reach_id else acc[1]
),
data["edges"],
[None, None]
)
sections = []
if hs.input_reach is not None:
sections += hs.input_reach.reach.profiles
if hs.output_reach is not None:
sections += hs.output_reach.reach.profiles
hs.input_section, hs.output_section = reduce(
lambda acc, s: (
s if s.pamhyr_id == input_section_id else acc[0],
s if s.pamhyr_id == output_section_id else acc[1]
),
sections,
[None, None]
)
data['hs_id'] = hs_id
hs._data = BasicHS._db_load(execute, data)
@ -211,24 +255,24 @@ class HydraulicStructure(SQLSubModel):
if self._output_reach is not None:
output_reach_id = self._output_reach.pamhyr_id
input_rk = -1
if self.input_rk is not None:
input_rk = self.input_rk
input_section = 'NULL'
if self.input_section is not None:
input_section = self.input_section.pamhyr_id
output_rk = -1
if self.output_rk is not None:
output_rk = self.output_rk
output_section = 'NULL'
if self.output_section is not None:
output_section = self.output_section.pamhyr_id
execute(
"INSERT INTO " +
"hydraulic_structures(" +
" pamhyr_id, name, enabled, input_rk, output_rk, " +
" pamhyr_id, name, enabled, input_section, output_section, " +
" input_reach, output_reach" +
") " +
"VALUES (" +
f"{self.pamhyr_id}, '{self._db_format(self._name)}', " +
f"{self._db_format(self.enabled)}, " +
f"{input_rk}, {output_rk}, " +
f"{input_section}, {output_section}, " +
f"{input_reach_id}, {output_reach_id}" +
")"
)
@ -261,23 +305,32 @@ class HydraulicStructure(SQLSubModel):
@property
def input_rk(self):
return self._input_rk
@input_rk.setter
def input_rk(self, input_rk):
if input_rk is not None:
input_rk = float(input_rk)
self._input_rk = input_rk
self._status.modified()
if self._input_section is None:
return None
return self._input_section.rk
@property
def output_rk(self):
return self._output_rk
if self._output_section is None:
return None
return self._output_section.rk
@output_rk.setter
def output_rk(self, output_rk):
self._output_rk = output_rk
@property
def input_section(self):
return self._input_section
@input_section.setter
def input_section(self, input_section):
self._input_section = input_section
self._status.modified()
@property
def output_section(self):
return self._output_section
@output_section.setter
def output_section(self, output_section):
self._output_section = output_section
self._status.modified()
@property

View File

@ -44,7 +44,7 @@ class Study(SQLModel):
def __init__(self, filename=None, init_new=True):
# Metadata
self._version = "0.1.0"
self._version = "0.1.1"
self.creation_date = datetime.now()
self.last_modification_date = datetime.now()
self.last_save_date = datetime.now()
@ -223,13 +223,12 @@ class Study(SQLModel):
def _create(self):
# Info (metadata)
self.execute(
"INSERT INTO info VALUES ('study_release', '0')"
)
self.execute(
"CREATE TABLE info(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)"
)
self.execute(
"INSERT INTO info VALUES ('study_release', '0')"
)
self.execute(
"INSERT INTO info VALUES ('version', " +
f"'{self._db_format(self._version)}')",
@ -272,7 +271,7 @@ class Study(SQLModel):
"INSERT INTO info VALUES ('study_release', '0')"
)
if int(minor) < 1:
if major == "0" and int(minor) < 1:
# Need to temporary disable the sqlite foreign keys
# checking to update db dans change the table id fk to
# table pamhyr_id fk
@ -282,7 +281,7 @@ class Study(SQLModel):
ok = self._update_submodel(version[0], data={})
if int(minor) < 1:
if major == "0" and int(minor) < 1:
# Reactivate foreign keys checking
self.execute(
"PRAGMA foreign_keys = ON;"
@ -355,7 +354,7 @@ class Study(SQLModel):
progress = progress if progress is not None else lambda: None
self.execute(
"INSERT INTO info VALUES ('study_release', " +
"INSERT OR REPLACE INTO info VALUES ('study_release', " +
f"'{self.status.version}')"
)

View File

@ -44,7 +44,7 @@ class SQLModel(SQL):
if exists and is_new:
os.remove(db)
self._db = sqlite3.connect(db)
self._db = sqlite3.connect(db, check_same_thread=False)
self._cur = self._db.cursor()
if is_new:
@ -244,6 +244,52 @@ class SQLSubModel(PamhyrID):
f"WHERE pamhyr_id = {pid}"
)
@classmethod
def _db_update_to_0_1_1_assoc_section_from_rk(
cls, execute, table,
reach_column="reach",
rk_column="rk",
section_column="section",
origin_version="0.1.0"):
kid = "pamhyr_id"
if origin_version == "0.0.*":
kid = "id"
els = execute(
"SELECT " +
f"{kid}, {reach_column}, {rk_column} " +
f"FROM {table}"
)
for row in els:
it = iter(row)
pid = next(it)
reach_id = next(it)
rk = next(it)
if reach_id == -1 or reach_id is None:
continue
section_id = -1
section = execute(
f"SELECT pamhyr_id FROM geometry_profileXYZ " +
f"WHERE reach == {reach_id} AND rk == {rk}"
)
if len(section) != 0:
section_id = section[0][0]
logger.info(
f"Update reach rk {rk}({reach_id}) to pid {section_id}"
)
execute(
f"UPDATE {table} " +
f"SET {section_column} = {section_id} " +
f"WHERE {kid} = {pid}"
)
@classmethod
def _db_load(cls, execute, data=None):
"""Load instance of this class from SQL data base

View File

@ -36,7 +36,7 @@ class SQL(object):
exist_ok=True
)
self._db = sqlite3.connect(db)
self._db = sqlite3.connect(db, check_same_thread=False)
self._cur = self._db.cursor()
if not exists:

View File

@ -20,6 +20,7 @@ import logging
import traceback
from tools import trace, timer
from functools import reduce
from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel,
@ -37,7 +38,7 @@ from PyQt5.QtWidgets import (
from View.Tools.PamhyrTable import PamhyrTableModel
from View.HydraulicStructures.UndoCommand import (
SetNameCommand, SetReachCommand, SetRkCommand,
SetNameCommand, SetReachCommand, SetSectionCommand,
SetEnabledCommand, AddCommand, DelCommand,
)
@ -65,7 +66,8 @@ class ComboBoxDelegate(QItemDelegate):
if reach is not None:
val = list(
map(
lambda rk: str(rk), reach.reach.get_rk()
lambda p: p.display_name(),
reach.reach.profiles
)
)
else:
@ -89,7 +91,20 @@ class ComboBoxDelegate(QItemDelegate):
def setModelData(self, editor, model, index):
text = str(editor.currentText())
model.setData(index, text)
if self._mode == "rk":
reach = self._data.hydraulic_structures\
.get(index.row())\
.input_reach
val = reduce(
lambda acc, p: p if text == p.display_name() else acc,
reach.reach.profiles,
None
)
else:
val = text
model.setData(index, val)
editor.close()
editor.deleteLater()
@ -127,10 +142,10 @@ class TableModel(PamhyrTableModel):
return self._trad['not_associated']
return n.name
elif self._headers[column] == "rk":
n = self._lst.get(row).input_rk
n = self._lst.get(row).input_section
if n is None:
return self._trad['not_associated']
return n
return n.display_name()
return QVariant()
@ -163,7 +178,7 @@ class TableModel(PamhyrTableModel):
value = None
self._undo.push(
SetRkCommand(
SetSectionCommand(
self._lst, row, value
)
)

View File

@ -66,20 +66,20 @@ class SetReachCommand(QUndoCommand):
i.input_rk = self._new_rk
class SetRkCommand(QUndoCommand):
def __init__(self, h_s_lst, index, rk):
class SetSectionCommand(QUndoCommand):
def __init__(self, h_s_lst, index, section):
QUndoCommand.__init__(self)
self._h_s_lst = h_s_lst
self._index = index
self._old = self._h_s_lst.get(self._index).input_rk
self._new = rk
self._old = self._h_s_lst.get(self._index).input_section
self._new = section
def undo(self):
self._h_s_lst.get(self._index).input_rk = self._old
self._h_s_lst.get(self._index).input_section = self._old
def redo(self):
self._h_s_lst.get(self._index).input_rk = self._new
self._h_s_lst.get(self._index).input_section = self._new
class SetEnabledCommand(QUndoCommand):