IC: Add scenario support.

scenarios
Pierre-Antoine Rouby 2024-09-17 12:01:02 +02:00
parent a5ecc2383c
commit a2ff3ecd9a
4 changed files with 85 additions and 70 deletions

View File

@ -75,7 +75,7 @@ class Data(SQLSubModel):
cls._db_update_to_0_1_0(execute, data) cls._db_update_to_0_1_0(execute, data)
if major == "0" and minor == "1": if major == "0" and minor == "1":
if release < 2: if int(release) < 2:
execute( execute(
"ALTER TABLE boundary_condition_data " + "ALTER TABLE boundary_condition_data " +
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE" "ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
@ -174,6 +174,9 @@ class Data(SQLSubModel):
return new return new
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
if not self.must_be_saved():
return True
pid = self._pamhyr_id pid = self._pamhyr_id
ind = data["ind"] ind = data["ind"]
data0 = self._db_format(str(self[0])) data0 = self._db_format(str(self[0]))

View File

@ -34,13 +34,13 @@ class Data(SQLSubModel):
reach=None, section=None, reach=None, section=None,
discharge: float = 0.0, discharge: float = 0.0,
height: float = 0.0, height: float = 0.0,
status=None): status=None,
super(Data, self).__init__(id) owner_scenario=-1):
super(Data, self).__init__(
self._status = status id=id, status=status,
owner_scenario=owner_scenario
)
self._reach = reach self._reach = reach
self._name = name self._name = name
self._comment = comment self._comment = comment
@ -62,6 +62,7 @@ class Data(SQLSubModel):
execute(f""" execute(f"""
CREATE TABLE initial_conditions{ext} ( CREATE TABLE initial_conditions{ext} (
{cls.create_db_add_pamhyr_id()}, {cls.create_db_add_pamhyr_id()},
deleted BOOLEAN NOT NULL DEFAULT FALSE,
ind INTEGER NOT NULL, ind INTEGER NOT NULL,
name TEXT NOT NULL, name TEXT NOT NULL,
comment TEXT NOT NULL, comment TEXT NOT NULL,
@ -93,6 +94,11 @@ class Data(SQLSubModel):
if int(release) < 1: if int(release) < 1:
cls._db_update_to_0_1_1(execute, data) cls._db_update_to_0_1_1(execute, data)
if int(release) < 2:
execute(
"ALTER TABLE initial_conditions " +
"ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT FALSE"
)
return cls._update_submodel(execute, version, data) return cls._update_submodel(execute, version, data)
@classmethod @classmethod
@ -137,29 +143,38 @@ class Data(SQLSubModel):
@classmethod @classmethod
def _db_load(cls, execute, data=None): def _db_load(cls, execute, data=None):
new = []
reach = data["reach"] reach = data["reach"]
scenario = data["scenario"]
loaded = data['loaded_pid']
if scenario is None:
return new
id = reach.pamhyr_id id = reach.pamhyr_id
table = execute( table = execute(
"SELECT pamhyr_id, ind, name, comment, " + "SELECT pamhyr_id, deleted, ind, name, comment, " +
"section, discharge, height " + "section, discharge, height, scenario " +
"FROM initial_conditions " + "FROM initial_conditions " +
f"WHERE reach = {id} " + f"WHERE reach = {id} " +
f"AND scenario = {scenario.id} " +
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " +
"ORDER BY ind ASC" "ORDER BY ind ASC"
) )
new = []
ok = True ok = True
for row in table: for row in table:
it = iter(row) it = iter(row)
pid = next(it) pid = next(it)
deleted = (next(it) == 1)
ind = next(it) ind = next(it)
name = next(it) name = next(it)
comment = next(it) comment = next(it)
section_id = next(it) section_id = next(it)
discharge = next(it) discharge = next(it)
height = next(it) height = next(it)
owner_scenario = next(it)
section = reduce( section = reduce(
lambda acc, s: ( lambda acc, s: (
@ -186,8 +201,12 @@ class Data(SQLSubModel):
section=section, section=section,
discharge=discharge, discharge=discharge,
height=height, height=height,
owner_scenario=owner_scenario
) )
if deleted:
nd.set_as_deleted()
loaded.add(pid)
new.append(d) new.append(d)
if not ok: if not ok:
@ -196,6 +215,12 @@ class Data(SQLSubModel):
f"for reach {reach.name} ({reach.pamhyr_id})" f"for reach {reach.name} ({reach.pamhyr_id})"
) )
# Recution only if no data found
if len(new) == 0:
data["scenario"] = scenario.parent
new += cls._db_load(execute, data)
data["scenario"] = scenario
return new return new
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
@ -203,14 +228,14 @@ class Data(SQLSubModel):
execute( execute(
"INSERT INTO " + "INSERT INTO " +
"initial_conditions(pamhyr_id, ind, name, comment, section, " + "initial_conditions(pamhyr_id, deleted, ind, name, comment, " +
"discharge, height, reach) " + "section, discharge, height, reach, scenario) " +
"VALUES (" + "VALUES (" +
f"{self.pamhyr_id}, " + f"{self.pamhyr_id}, {self._db_format(self.is_deleted())}, " +
f"{ind}, '{self._db_format(self.name)}', " + f"{ind}, '{self._db_format(self.name)}', " +
f"'{self._db_format(self._comment)}', " + f"'{self._db_format(self._comment)}', " +
f"{self._section.id}, {self._discharge}, {self._height}, " + f"{self._section.id}, {self._discharge}, {self._height}, " +
f"{self._reach.id}" + f"{self._reach.id}, {self._status.scenario_id}" +
")" ")"
) )
@ -239,7 +264,7 @@ class Data(SQLSubModel):
val = self._name val = self._name
elif key == "comment": elif key == "comment":
val = self._comment val = self._comment
elif key == "rk": elif key == "rk" or key == "section":
val = self._section val = self._section
elif key == "speed": elif key == "speed":
val = self._speed val = self._speed
@ -282,7 +307,7 @@ class Data(SQLSubModel):
self._name = str(value) self._name = str(value)
elif key == "comment": elif key == "comment":
self._comment = str(value) self._comment = str(value)
elif key == "rk": elif key == "rk" or key == "section":
self._section = value self._section = value
self._update_from_rk() self._update_from_rk()
elif key == "speed": elif key == "speed":
@ -298,7 +323,7 @@ class Data(SQLSubModel):
self._height = float(value) self._height = float(value)
self._update_from_height() self._update_from_height()
self._status.modified() self.modified()
class InitialConditions(SQLSubModel): class InitialConditions(SQLSubModel):
@ -361,11 +386,16 @@ class InitialConditions(SQLSubModel):
@reach.setter @reach.setter
def reach(self, new): def reach(self, new):
self._reach = reach self._reach = reach
self._status.modified() self.modified()
@property @property
def data(self): def data(self):
return self._data.copy() return list(
filter(
lambda el: not el.is_deleted(),
self._data
)
)
@data.setter @data.setter
def data(self, data): def data(self, data):
@ -376,34 +406,46 @@ class InitialConditions(SQLSubModel):
def set(self, index, data): def set(self, index, data):
self._data.insert(index, data) self._data.insert(index, data)
self._status.modified() self.modified()
def new(self, index): def new(self, index):
n = Data(reach=self._reach, status=self._status) n = Data(reach=self._reach, status=self._status)
self._data.insert(index, n) self._data.insert(index, n)
self._status.modified() self.modified()
def new_from_data(self, rk, discharge, elevation): def new_from_data(self, rk, discharge, elevation):
n = Data(reach=self._reach, status=self._status) n = Data(reach=self._reach, status=self._status)
n['rk'] = rk section = reduce(
lambda acc, s: (
s if s.rk == rk else acc
),
self._reach.reach.profiles,
None
)
n['section'] = section
n['discharge'] = discharge n['discharge'] = discharge
n['elevation'] = elevation n['elevation'] = elevation
return n return n
def insert(self, index, data): def insert(self, index, data):
self._data.insert(index, data) if data in self._data:
self._status.modified() data.set_as_not_deleted()
else:
self._data.insert(index, data)
self.modified()
def delete(self, data): def delete(self, data):
self._data = list( list(
filter( filter(
lambda x: x not in data, lambda x: x.set_as_deleted(),
self._data self._data
) )
) )
self._status.modified() self.modified()
def delete_i(self, indexes): def delete_i(self, indexes):
data = list( data = list(
@ -419,7 +461,7 @@ class InitialConditions(SQLSubModel):
def sort(self, reverse=False, key=None): def sort(self, reverse=False, key=None):
self._data.sort(reverse=reverse, key=key) self._data.sort(reverse=reverse, key=key)
self._status.modified() self.modified()
def _data_get(self, key): def _data_get(self, key):
return list( return list(
@ -443,27 +485,9 @@ class InitialConditions(SQLSubModel):
def get_discharge(self): def get_discharge(self):
return self._data_get("discharge") return self._data_get("discharge")
def _sort_by_z_and_rk(self, profiles):
profiles.sort(
reverse=False,
key=lambda p: p.rk
)
first_z = profiles[0].z()
last_z = profiles[-1].z()
if first_z > last_z:
profiles.sort(
reverse=True,
key=lambda p: p.rk
)
def generate_growing_constante_height(self, height: float, def generate_growing_constante_height(self, height: float,
compute_discharge: bool): compute_discharge: bool):
profiles = self._reach.reach.profiles.copy() profiles = self._reach.reach.profiles.copy()
self._sort_by_z_and_rk(profiles)
previous_elevation = -99999.99 previous_elevation = -99999.99
data_discharge = {} data_discharge = {}
@ -478,7 +502,7 @@ class InitialConditions(SQLSubModel):
incline = self._reach.reach.get_incline_median_mean() incline = self._reach.reach.get_incline_median_mean()
logger.debug(f"incline = {incline}") logger.debug(f"incline = {incline}")
self._data = [] self._data = []
for profile in profiles: for profile in reversed(profiles):
width = profile.wet_width(profile.z_min() + height) width = profile.wet_width(profile.z_min() + height)
frictions = self._reach.frictions.frictions frictions = self._reach.frictions.frictions
strickler = None strickler = None
@ -509,20 +533,17 @@ class InitialConditions(SQLSubModel):
logger.debug(f" discharge = {discharge}") logger.debug(f" discharge = {discharge}")
new = Data(reach=self._reach, status=self._status) new = Data(reach=self._reach, status=self._status)
new["rk"] = profile.rk new["rk"] = profile
new["discharge"] = discharge new["discharge"] = discharge
new["elevation"] = elevation new["elevation"] = elevation
previous_elevation = elevation previous_elevation = elevation
self._data.append(new) self._data.append(new)
self._generate_resort_data(profiles) self._data.reverse()
def generate_discharge(self, discharge: float, compute_height: bool): def generate_discharge(self, discharge: float, compute_height: bool):
profiles = self._reach.reach.profiles.copy() profiles = self._reach.reach.profiles.copy()
self._sort_by_z_and_rk(profiles)
previous_elevation = -99999.99 previous_elevation = -99999.99
data_height = {} data_height = {}
@ -537,7 +558,7 @@ class InitialConditions(SQLSubModel):
incline = self._reach.reach.get_incline_median_mean() incline = self._reach.reach.get_incline_median_mean()
logger.debug(f"incline = {incline}") logger.debug(f"incline = {incline}")
self._data = [] self._data = []
for profile in profiles: for profile in reversed(profiles):
width = profile.width_approximation() width = profile.width_approximation()
frictions = self._reach.frictions.frictions frictions = self._reach.frictions.frictions
strickler = None strickler = None
@ -567,21 +588,11 @@ class InitialConditions(SQLSubModel):
logger.debug(f" height = {height}") logger.debug(f" height = {height}")
new = Data(reach=self._reach, status=self._status) new = Data(reach=self._reach, status=self._status)
new["rk"] = profile.rk new["section"] = profile
new["discharge"] = discharge new["discharge"] = discharge
new["elevation"] = elevation new["elevation"] = elevation
previous_elevation = elevation previous_elevation = elevation
self._data.append(new) self._data.append(new)
self._generate_resort_data(profiles) self._data.reverse()
def _generate_resort_data(self, profiles):
is_reverse = False
if profiles[0].rk > profiles[-1].rk:
is_reverse = True
self._data.sort(
reverse=not is_reverse,
key=lambda d: d['rk']
)

View File

@ -64,7 +64,8 @@ class InitialConditionsDict(PamhyrModelDict):
execute( execute(
"DELETE FROM initial_conditions " + "DELETE FROM initial_conditions " +
f"WHERE reach = '{reach.id}'" f"WHERE reach = '{reach.id}' " +
f"AND scenario = {self._status.scenario_id}"
) )
ok &= self._dict[reach]._db_save(execute, data) ok &= self._dict[reach]._db_save(execute, data)

View File

@ -32,9 +32,9 @@ class PamhyrModelDict(SQLSubModel):
_sub_classes = [] _sub_classes = []
def __init__(self, status=None): def __init__(self, status=None):
super(PamhyrModelDict, self).__init__() super(PamhyrModelDict, self).__init__(
status=status
self._status = status )
self._dict = {} self._dict = {}