mirror of https://gitlab.com/pamhyr/pamhyr2
Merge branch 'split_reach' into dev_dylan
commit
cdbcb2b539
|
|
@ -277,3 +277,10 @@ class BasicHS(SQLSubModel):
|
|||
|
||||
def convert(self, new_type):
|
||||
return new_type(id=self.id, name=self.name, status=self._status)
|
||||
|
||||
def cloned(self):
|
||||
new = type(self)(name=self._name, status=self._status)
|
||||
new._enabled = self._enabled
|
||||
new._data = [value.cloned() for value in self._data]
|
||||
new.modified()
|
||||
return new
|
||||
|
|
|
|||
|
|
@ -208,3 +208,11 @@ class BHSValue(SQLSubModel):
|
|||
def value(self, value):
|
||||
self._value = self._type(value)
|
||||
self.modified()
|
||||
|
||||
def cloned(self):
|
||||
return BHSValue(
|
||||
name=self._name,
|
||||
type=self._type,
|
||||
value=self._value,
|
||||
status=self._status
|
||||
)
|
||||
|
|
|
|||
|
|
@ -427,6 +427,18 @@ class HydraulicStructure(SQLSubModel):
|
|||
def basic_structures(self):
|
||||
return self.lst.copy()
|
||||
|
||||
def cloned_for(self, input_reach, input_section,
|
||||
output_reach, output_section):
|
||||
new = HydraulicStructure(name=self._name, status=self._status)
|
||||
new._enabled = self._enabled
|
||||
new._input_reach = input_reach
|
||||
new._input_section = input_section
|
||||
new._output_reach = output_reach
|
||||
new._output_section = output_section
|
||||
new._data = [structure.cloned() for structure in self.lst]
|
||||
new.modified()
|
||||
return new
|
||||
|
||||
def basic_structure(self, index: int):
|
||||
if len(self._data) == 0:
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -61,6 +61,71 @@ class HydraulicStructureList(PamhyrModelList):
|
|||
self.modified()
|
||||
return n
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
profiles = reach.reach.profiles
|
||||
split_index = profiles.index(profile)
|
||||
sections1 = dict(zip(
|
||||
profiles[:split_index + 1],
|
||||
reach1.reach.profiles
|
||||
))
|
||||
sections2 = dict(zip(
|
||||
profiles[split_index:],
|
||||
reach2.reach.profiles
|
||||
))
|
||||
|
||||
def split_endpoint(endpoint_reach, section):
|
||||
if endpoint_reach is not reach:
|
||||
return endpoint_reach, section
|
||||
if section not in profiles:
|
||||
return endpoint_reach, section
|
||||
|
||||
index = profiles.index(section)
|
||||
if index < split_index:
|
||||
return reach1, sections1[section]
|
||||
return reach2, sections2[section]
|
||||
|
||||
structures = [
|
||||
structure
|
||||
for structure in self.lst
|
||||
if (structure.input_reach is reach or
|
||||
structure.output_reach is reach)
|
||||
]
|
||||
|
||||
for structure in structures:
|
||||
input_reach, input_section = split_endpoint(
|
||||
structure.input_reach,
|
||||
structure.input_section
|
||||
)
|
||||
output_reach, output_section = split_endpoint(
|
||||
structure.output_reach,
|
||||
structure.output_section
|
||||
)
|
||||
self._lst.append(structure.cloned_for(
|
||||
input_reach,
|
||||
input_section,
|
||||
output_reach,
|
||||
output_section
|
||||
))
|
||||
|
||||
if len(structures) != 0:
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def enabled_reaches_list(self):
|
||||
return [
|
||||
structure
|
||||
for structure in self.lst
|
||||
if (structure.input_reach is None or
|
||||
(not structure.input_reach.is_deleted() and
|
||||
structure.input_reach.is_enable()))
|
||||
]
|
||||
|
||||
def get_for_enabled_reaches(self, index):
|
||||
structures = self.enabled_reaches_list
|
||||
if not 0 <= index < len(structures):
|
||||
return None
|
||||
return structures[index]
|
||||
|
||||
def __copy__(self):
|
||||
new = HydraulicStructureList()
|
||||
|
||||
|
|
|
|||
|
|
@ -256,6 +256,17 @@ class Data(SQLSubModel):
|
|||
)
|
||||
return new
|
||||
|
||||
def cloned_for(self, reach, section):
|
||||
return Data(
|
||||
name=self._name,
|
||||
comment=self._comment,
|
||||
section=section,
|
||||
discharge=self._discharge,
|
||||
height=self._height,
|
||||
reach=reach,
|
||||
status=self._status,
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
|
@ -505,6 +516,20 @@ class InitialConditions(SQLSubModel):
|
|||
for data in self._data:
|
||||
data.set_as_deleted()
|
||||
|
||||
def _splited_for(self, reach, sections):
|
||||
new = InitialConditions(reach=reach, status=self._status)
|
||||
|
||||
new._data = [
|
||||
data.cloned_for(reach, sections[data["section"]])
|
||||
for data in self.data
|
||||
if data["section"] in sections
|
||||
]
|
||||
|
||||
if len(new._data) != 0:
|
||||
new.modified()
|
||||
|
||||
return new
|
||||
|
||||
def generate_growing_constant_depth(self, height: float,
|
||||
compute_discharge: bool):
|
||||
profiles = self._reach.reach.profiles.copy()
|
||||
|
|
|
|||
|
|
@ -88,3 +88,28 @@ class InitialConditionsDict(PamhyrModelDict):
|
|||
new = InitialConditions(reach=reach, status=self._status)
|
||||
self.set(reach, new)
|
||||
return new
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
if reach not in self._dict:
|
||||
return
|
||||
|
||||
profiles = reach.reach.profiles
|
||||
split_index = profiles.index(profile)
|
||||
|
||||
sections1 = dict(zip(
|
||||
profiles[:split_index + 1],
|
||||
reach1.reach.profiles
|
||||
))
|
||||
sections2 = dict(zip(
|
||||
profiles[split_index:],
|
||||
reach2.reach.profiles
|
||||
))
|
||||
|
||||
self.set(
|
||||
reach1,
|
||||
self._dict[reach]._splited_for(reach1, sections1)
|
||||
)
|
||||
self.set(
|
||||
reach2,
|
||||
self._dict[reach]._splited_for(reach2, sections2)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -359,3 +359,60 @@ class InitialConditionsAdisTS(SQLSubModel):
|
|||
x.set_as_not_deleted()
|
||||
|
||||
self.modified()
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
split_rk = profile.rk
|
||||
reach_rks = reach.reach.get_rk()
|
||||
if len(reach_rks) == 0:
|
||||
return
|
||||
|
||||
lower_reach_rk = min(reach_rks)
|
||||
upper_reach_rk = max(reach_rks)
|
||||
parts = [
|
||||
(reach1.id, lower_reach_rk, split_rk),
|
||||
(reach2.id, split_rk, upper_reach_rk),
|
||||
]
|
||||
specifications = [
|
||||
specification
|
||||
for specification in self._data
|
||||
if (not specification.is_deleted() and
|
||||
specification.reach == reach.id)
|
||||
]
|
||||
|
||||
for specification in specifications:
|
||||
begin = specification.start_rk
|
||||
end = specification.end_rk
|
||||
if begin is None or end is None:
|
||||
continue
|
||||
|
||||
lower, upper = sorted((begin, end))
|
||||
reverse = begin > end
|
||||
|
||||
for new_reach, part_lower, part_upper in parts:
|
||||
clipped_lower = max(lower, part_lower)
|
||||
clipped_upper = min(upper, part_upper)
|
||||
if clipped_lower > clipped_upper:
|
||||
continue
|
||||
|
||||
start_rk = clipped_upper if reverse else clipped_lower
|
||||
end_rk = clipped_lower if reverse else clipped_upper
|
||||
self._data.append(specification.cloned_for(
|
||||
new_reach, start_rk, end_rk
|
||||
))
|
||||
|
||||
if len(specifications) != 0:
|
||||
self.modified()
|
||||
|
||||
def get_specs_for_enabled_reaches(self, reaches):
|
||||
enabled_reaches = {
|
||||
reach.id
|
||||
for reach in reaches
|
||||
if not reach.is_deleted() and reach.is_enable()
|
||||
}
|
||||
return [
|
||||
specification
|
||||
for specification in self._data
|
||||
if (not specification.is_deleted() and
|
||||
(specification.reach in (None, -1) or
|
||||
specification.reach in enabled_reaches))
|
||||
]
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@ class InitialConditionsAdisTSList(PamhyrModelList):
|
|||
self._status.modified()
|
||||
return n
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
for initial_condition in self.lst:
|
||||
initial_condition.split_reach(
|
||||
reach, profile, reach1, reach2
|
||||
)
|
||||
|
||||
@property
|
||||
def Initial_Conditions_List(self):
|
||||
return self.lst
|
||||
|
|
|
|||
|
|
@ -31,10 +31,12 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
_sub_classes = []
|
||||
|
||||
def __init__(self, id: int = -1, name: str = "",
|
||||
status=None, owner_scenario=None):
|
||||
super(ICAdisTSSpec, self).__init__()
|
||||
|
||||
self._status = status
|
||||
status=None, owner_scenario=-1):
|
||||
super(ICAdisTSSpec, self).__init__(
|
||||
id=id,
|
||||
status=status,
|
||||
owner_scenario=owner_scenario
|
||||
)
|
||||
|
||||
self._name_section = name
|
||||
self._reach = None
|
||||
|
|
@ -234,7 +236,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@name.setter
|
||||
def name(self, name):
|
||||
self._name_section = name
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def reach(self):
|
||||
|
|
@ -243,7 +245,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@reach.setter
|
||||
def reach(self, reach):
|
||||
self._reach = reach
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def start_rk(self):
|
||||
|
|
@ -252,7 +254,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@start_rk.setter
|
||||
def start_rk(self, start_rk):
|
||||
self._start_rk = start_rk
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def end_rk(self):
|
||||
|
|
@ -261,7 +263,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@end_rk.setter
|
||||
def end_rk(self, end_rk):
|
||||
self._end_rk = end_rk
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def concentration(self):
|
||||
|
|
@ -270,7 +272,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@concentration.setter
|
||||
def concentration(self, concentration):
|
||||
self._concentration = concentration
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def eg(self):
|
||||
|
|
@ -279,7 +281,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@eg.setter
|
||||
def eg(self, eg):
|
||||
self._eg = eg
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def em(self):
|
||||
|
|
@ -288,7 +290,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@em.setter
|
||||
def em(self, em):
|
||||
self._em = em
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def ed(self):
|
||||
|
|
@ -297,7 +299,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@ed.setter
|
||||
def ed(self, ed):
|
||||
self._ed = ed
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def rate(self):
|
||||
|
|
@ -306,7 +308,7 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@rate.setter
|
||||
def rate(self, rate):
|
||||
self._rate = rate
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
|
|
@ -315,4 +317,18 @@ class ICAdisTSSpec(SQLSubModel):
|
|||
@enabled.setter
|
||||
def enabled(self, enabled):
|
||||
self._enabled = enabled
|
||||
self._status.modified()
|
||||
self.modified()
|
||||
|
||||
def cloned_for(self, reach, start_rk, end_rk):
|
||||
new = ICAdisTSSpec(name=self._name_section, status=self._status)
|
||||
new._reach = reach
|
||||
new._start_rk = start_rk
|
||||
new._end_rk = end_rk
|
||||
new._concentration = self._concentration
|
||||
new._eg = self._eg
|
||||
new._em = self._em
|
||||
new._ed = self._ed
|
||||
new._rate = self._rate
|
||||
new._enabled = self._enabled
|
||||
new.modified()
|
||||
return new
|
||||
|
|
|
|||
|
|
@ -227,3 +227,42 @@ class InitialConditionsTemperature(SQLSubModel):
|
|||
x.set_as_not_deleted()
|
||||
|
||||
self.modified()
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
parts = []
|
||||
for new_reach in (reach1, reach2):
|
||||
rks = new_reach.reach.get_rk()
|
||||
if rks:
|
||||
parts.append((new_reach.id, min(rks), max(rks)))
|
||||
|
||||
specifications = [
|
||||
specification
|
||||
for specification in self._data
|
||||
if (not specification.is_deleted() and
|
||||
specification.reach == reach.id)
|
||||
]
|
||||
clones = []
|
||||
|
||||
for specification in specifications:
|
||||
begin = specification.start_rk
|
||||
end = specification.end_rk
|
||||
if begin is None or end is None:
|
||||
continue
|
||||
|
||||
lower, upper = sorted((begin, end))
|
||||
reverse = begin > end
|
||||
for new_reach, part_lower, part_upper in parts:
|
||||
clipped_lower = max(lower, part_lower)
|
||||
clipped_upper = min(upper, part_upper)
|
||||
if clipped_lower > clipped_upper:
|
||||
continue
|
||||
|
||||
start_rk = clipped_upper if reverse else clipped_lower
|
||||
end_rk = clipped_lower if reverse else clipped_upper
|
||||
clones.append(specification.cloned_for(
|
||||
new_reach, start_rk, end_rk
|
||||
))
|
||||
|
||||
if clones:
|
||||
self._data.extend(clones)
|
||||
self.modified()
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@ class InitialConditionsTemperatureList(PamhyrModelList):
|
|||
self._status.modified()
|
||||
return n
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
for initial_condition in self.lst:
|
||||
initial_condition.split_reach(
|
||||
reach, profile, reach1, reach2
|
||||
)
|
||||
|
||||
@property
|
||||
def Initial_Conditions_List(self):
|
||||
return self.lst
|
||||
|
|
|
|||
|
|
@ -200,3 +200,15 @@ class ICTemperatureSpec(SQLSubModel):
|
|||
def temperature(self, temperature):
|
||||
self._temperature = temperature
|
||||
self._status.modified()
|
||||
|
||||
def cloned_for(self, reach, start_rk, end_rk):
|
||||
new = ICTemperatureSpec(
|
||||
name=self._name_section,
|
||||
status=self._status
|
||||
)
|
||||
new._reach = reach
|
||||
new._start_rk = start_rk
|
||||
new._end_rk = end_rk
|
||||
new._temperature = self._temperature
|
||||
new.modified()
|
||||
return new
|
||||
|
|
|
|||
|
|
@ -196,6 +196,13 @@ class Data(SQLSubModel):
|
|||
def __setitem__(self, key, value):
|
||||
self._data[key] = self._types[key](value)
|
||||
|
||||
def cloned(self):
|
||||
return Data(
|
||||
self[0], self[1],
|
||||
types=self._types,
|
||||
status=self._status
|
||||
)
|
||||
|
||||
|
||||
class LateralContribution(SQLSubModel):
|
||||
_sub_classes = [Data]
|
||||
|
|
@ -511,6 +518,15 @@ class LateralContribution(SQLSubModel):
|
|||
def has_reach(self):
|
||||
return self._reach is not None
|
||||
|
||||
def cloned_for(self, reach, begin_section, end_section):
|
||||
new = type(self)(name=self._name, status=self._status)
|
||||
new._reach = reach
|
||||
new._begin_section = begin_section
|
||||
new._end_section = end_section
|
||||
new._data = [data.cloned() for data in self.data]
|
||||
new.modified()
|
||||
return new
|
||||
|
||||
@property
|
||||
def begin_rk(self):
|
||||
if self._begin_section is None:
|
||||
|
|
|
|||
|
|
@ -71,6 +71,89 @@ class LateralContributionList(PamhyrModelListWithTab):
|
|||
self._status.modified()
|
||||
return n
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
profiles = reach.reach.profiles
|
||||
split_index = profiles.index(profile)
|
||||
|
||||
parts = [
|
||||
(
|
||||
reach1,
|
||||
0,
|
||||
split_index,
|
||||
dict(zip(
|
||||
profiles[:split_index + 1],
|
||||
reach1.reach.profiles
|
||||
))
|
||||
),
|
||||
(
|
||||
reach2,
|
||||
split_index,
|
||||
len(profiles) - 1,
|
||||
dict(zip(
|
||||
profiles[split_index:],
|
||||
reach2.reach.profiles
|
||||
))
|
||||
),
|
||||
]
|
||||
|
||||
for tab in self._tabs:
|
||||
contributions = [
|
||||
contribution
|
||||
for contribution in self.get_tab(tab)
|
||||
if contribution.reach is reach
|
||||
]
|
||||
|
||||
for contribution in contributions:
|
||||
if (contribution.begin_section not in profiles or
|
||||
contribution.end_section not in profiles):
|
||||
continue
|
||||
|
||||
begin = profiles.index(contribution.begin_section)
|
||||
end = profiles.index(contribution.end_section)
|
||||
lower, upper = sorted((begin, end))
|
||||
reverse = begin > end
|
||||
clones = []
|
||||
|
||||
for new_reach, part_lower, part_upper, sections in parts:
|
||||
clipped_lower = max(lower, part_lower)
|
||||
clipped_upper = min(upper, part_upper)
|
||||
if clipped_lower > clipped_upper:
|
||||
continue
|
||||
|
||||
begin_index = (
|
||||
clipped_upper if reverse else clipped_lower
|
||||
)
|
||||
end_index = (
|
||||
clipped_lower if reverse else clipped_upper
|
||||
)
|
||||
clones.append(contribution.cloned_for(
|
||||
new_reach,
|
||||
sections[profiles[begin_index]],
|
||||
sections[profiles[end_index]]
|
||||
))
|
||||
|
||||
if len(clones) == 0:
|
||||
continue
|
||||
|
||||
self._tabs[tab].extend(clones)
|
||||
|
||||
self._status.modified()
|
||||
|
||||
def get_tab_for_enabled_reaches(self, tab):
|
||||
return [
|
||||
contribution
|
||||
for contribution in self.get_tab(tab)
|
||||
if (contribution.reach is None or
|
||||
(not contribution.reach.is_deleted() and
|
||||
contribution.reach.is_enable()))
|
||||
]
|
||||
|
||||
def get_for_enabled_reaches(self, tab, index):
|
||||
contributions = self.get_tab_for_enabled_reaches(tab)
|
||||
if not 0 <= index < len(contributions):
|
||||
return None
|
||||
return contributions[index]
|
||||
|
||||
def __copy__(self):
|
||||
new = LateralContributionList()
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,13 @@ class Data(SQLSubModel):
|
|||
def __setitem__(self, key, value):
|
||||
self._data[key] = self._types[key](value)
|
||||
|
||||
def cloned(self):
|
||||
return Data(
|
||||
self[0], self[1],
|
||||
types=self._types,
|
||||
status=self._status
|
||||
)
|
||||
|
||||
|
||||
class LateralContributionAdisTS(SQLSubModel):
|
||||
_sub_classes = [Data]
|
||||
|
|
@ -477,6 +484,18 @@ class LateralContributionAdisTS(SQLSubModel):
|
|||
self._end_rk = end_rk
|
||||
self.modified()
|
||||
|
||||
def cloned_for(self, reach, begin_rk, end_rk):
|
||||
new = LateralContributionAdisTS(
|
||||
pollutant=self._pollutant,
|
||||
status=self._status
|
||||
)
|
||||
new._reach = reach
|
||||
new._begin_rk = begin_rk
|
||||
new._end_rk = end_rk
|
||||
new._data = [data.cloned() for data in self.data]
|
||||
new.modified()
|
||||
return new
|
||||
|
||||
@property
|
||||
def _default_0(self):
|
||||
return self._types[0](0)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,46 @@ class LateralContributionsAdisTSList(PamhyrModelList):
|
|||
self._status.modified()
|
||||
return n
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
parts = []
|
||||
for new_reach in (reach1, reach2):
|
||||
rks = new_reach.reach.get_rk()
|
||||
if len(rks) == 0:
|
||||
continue
|
||||
parts.append((new_reach.id, min(rks), max(rks)))
|
||||
|
||||
contributions = [
|
||||
contribution
|
||||
for contribution in self.lst
|
||||
if contribution.reach == reach.id
|
||||
]
|
||||
clones = []
|
||||
|
||||
for contribution in contributions:
|
||||
begin = contribution.begin_rk
|
||||
end = contribution.end_rk
|
||||
if begin is None or end is None:
|
||||
continue
|
||||
|
||||
lower, upper = sorted((begin, end))
|
||||
reverse = begin > end
|
||||
|
||||
for new_reach, part_lower, part_upper in parts:
|
||||
clipped_lower = max(lower, part_lower)
|
||||
clipped_upper = min(upper, part_upper)
|
||||
if clipped_lower > clipped_upper:
|
||||
continue
|
||||
|
||||
begin_rk = clipped_upper if reverse else clipped_lower
|
||||
end_rk = clipped_lower if reverse else clipped_upper
|
||||
clones.append(contribution.cloned_for(
|
||||
new_reach, begin_rk, end_rk
|
||||
))
|
||||
|
||||
if len(clones) != 0:
|
||||
self._lst.extend(clones)
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def Lat_Cont_List(self):
|
||||
return self.lst
|
||||
|
|
|
|||
|
|
@ -979,4 +979,26 @@ Last export at: @date."""
|
|||
self._add_edge(r1)
|
||||
self._add_edge(r2)
|
||||
|
||||
self._initial_conditions.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
self._lateral_contribution.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
self._hydraulic_structures.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
self._InitialConditionsAdisTS.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
self._LateralContributionsAdisTS.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
self._InitialConditionsTemperature.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
self._WeatherParameters.split_reach(
|
||||
reach, profile, r1, r2
|
||||
)
|
||||
|
||||
return r1, r2
|
||||
|
|
|
|||
|
|
@ -153,6 +153,13 @@ class Data(SQLSubModel):
|
|||
def __setitem__(self, key, value):
|
||||
self._data[key] = self._types[key](value)
|
||||
|
||||
def cloned(self):
|
||||
return Data(
|
||||
self[0], self[1],
|
||||
types=self._types,
|
||||
status=self._status
|
||||
)
|
||||
|
||||
|
||||
class WeatherParametersDefault(SQLSubModel):
|
||||
def __init__(self, type: str, value: float = 0.0,
|
||||
|
|
@ -580,6 +587,15 @@ class WeatherParameters(SQLSubModel):
|
|||
self._end_section = section
|
||||
self.modified()
|
||||
|
||||
def cloned_for(self, reach, begin_section, end_section):
|
||||
new = type(self)(name=self._name, status=self._status)
|
||||
new._reach = reach
|
||||
new._begin_section = begin_section
|
||||
new._end_section = end_section
|
||||
new._data = [data.cloned() for data in self.data]
|
||||
new.modified()
|
||||
return new
|
||||
|
||||
@property
|
||||
def header(self):
|
||||
return self._header.copy()
|
||||
|
|
|
|||
|
|
@ -161,6 +161,64 @@ class WeatherParametersList(PamhyrModelList):
|
|||
self._status.modified()
|
||||
return n
|
||||
|
||||
def split_reach(self, reach, profile, reach1, reach2):
|
||||
profiles = reach.reach.profiles
|
||||
split_index = profiles.index(profile)
|
||||
parts = [
|
||||
(
|
||||
reach1,
|
||||
0,
|
||||
split_index,
|
||||
dict(zip(
|
||||
profiles[:split_index + 1],
|
||||
reach1.reach.profiles
|
||||
))
|
||||
),
|
||||
(
|
||||
reach2,
|
||||
split_index,
|
||||
len(profiles) - 1,
|
||||
dict(zip(
|
||||
profiles[split_index:],
|
||||
reach2.reach.profiles
|
||||
))
|
||||
),
|
||||
]
|
||||
weather_parameters = [
|
||||
weather_parameter
|
||||
for weather_parameter in self.lst
|
||||
if weather_parameter.reach is reach
|
||||
]
|
||||
clones = []
|
||||
|
||||
for weather_parameter in weather_parameters:
|
||||
if (weather_parameter.begin_section not in profiles or
|
||||
weather_parameter.end_section not in profiles):
|
||||
continue
|
||||
|
||||
begin = profiles.index(weather_parameter.begin_section)
|
||||
end = profiles.index(weather_parameter.end_section)
|
||||
lower, upper = sorted((begin, end))
|
||||
reverse = begin > end
|
||||
|
||||
for new_reach, part_lower, part_upper, sections in parts:
|
||||
clipped_lower = max(lower, part_lower)
|
||||
clipped_upper = min(upper, part_upper)
|
||||
if clipped_lower > clipped_upper:
|
||||
continue
|
||||
|
||||
begin_index = clipped_upper if reverse else clipped_lower
|
||||
end_index = clipped_lower if reverse else clipped_upper
|
||||
clones.append(weather_parameter.cloned_for(
|
||||
new_reach,
|
||||
sections[profiles[begin_index]],
|
||||
sections[profiles[end_index]]
|
||||
))
|
||||
|
||||
if clones:
|
||||
self._lst.extend(clones)
|
||||
self._status.modified()
|
||||
|
||||
@property
|
||||
def Weather_Parameters_List(self):
|
||||
return self.lst
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import tempfile
|
|||
from Model.Status import StudyStatus
|
||||
from Model.Study import Study
|
||||
from Model.River import River
|
||||
from Model.LateralContribution.LateralContributionTypes import LateralContrib
|
||||
from Model.HydraulicStructures.Basic.Types import DischargeWeir
|
||||
|
||||
|
||||
class StudyTestCase(unittest.TestCase):
|
||||
|
|
@ -287,3 +289,89 @@ class RiverTestCase(unittest.TestCase):
|
|||
edges = river.edges()
|
||||
self.assertEqual(edges[0], e0)
|
||||
self.assertEqual(edges[1], e1)
|
||||
|
||||
def test_split_reach_splits_initial_conditions(self):
|
||||
status = StudyStatus()
|
||||
river = River(status=status)
|
||||
node1 = river.add_node()
|
||||
node2 = river.add_node(x=40.0)
|
||||
reach = river.add_edge(node1, node2)
|
||||
|
||||
profiles = []
|
||||
for index in range(5):
|
||||
profile = reach.reach.insert(index)
|
||||
profile.rk = index * 10.0
|
||||
profile.insert(0)
|
||||
profiles.append(profile)
|
||||
|
||||
initial_conditions = river.initial_conditions.get(reach)
|
||||
for index, profile in enumerate(profiles):
|
||||
data = initial_conditions.new_from_data(
|
||||
profile.rk,
|
||||
discharge=100.0 + index,
|
||||
elevation=10.0 + index,
|
||||
)
|
||||
initial_conditions.insert(index, data)
|
||||
|
||||
reach1, reach2 = river._split_reach(reach, profiles[2])
|
||||
conditions1 = river.initial_conditions.get(reach1).data
|
||||
conditions2 = river.initial_conditions.get(reach2).data
|
||||
|
||||
self.assertEqual(
|
||||
[data["discharge"] for data in conditions1],
|
||||
[100.0, 101.0, 102.0]
|
||||
)
|
||||
self.assertEqual(
|
||||
[data["discharge"] for data in conditions2],
|
||||
[102.0, 103.0, 104.0]
|
||||
)
|
||||
self.assertEqual(
|
||||
[data["section"] for data in conditions1],
|
||||
reach1.reach.profiles
|
||||
)
|
||||
self.assertEqual(
|
||||
[data["section"] for data in conditions2],
|
||||
reach2.reach.profiles
|
||||
)
|
||||
self.assertTrue(all(
|
||||
data._reach is reach1 for data in conditions1
|
||||
))
|
||||
self.assertTrue(all(
|
||||
data._reach is reach2 for data in conditions2
|
||||
))
|
||||
|
||||
def test_split_reach_keeps_partial_initial_conditions_in_scope(self):
|
||||
status = StudyStatus()
|
||||
river = River(status=status)
|
||||
node1 = river.add_node()
|
||||
node2 = river.add_node(x=40.0)
|
||||
reach = river.add_edge(node1, node2)
|
||||
|
||||
profiles = []
|
||||
for index in range(5):
|
||||
profile = reach.reach.insert(index)
|
||||
profile.rk = index * 10.0
|
||||
profile.insert(0)
|
||||
profiles.append(profile)
|
||||
|
||||
initial_conditions = river.initial_conditions.get(reach)
|
||||
for index in (1, 3):
|
||||
data = initial_conditions.new_from_data(
|
||||
profiles[index].rk,
|
||||
discharge=100.0 + index,
|
||||
elevation=10.0 + index,
|
||||
)
|
||||
initial_conditions.insert(len(initial_conditions.data), data)
|
||||
|
||||
reach1, reach2 = river._split_reach(reach, profiles[2])
|
||||
|
||||
self.assertEqual(
|
||||
[data["discharge"]
|
||||
for data in river.initial_conditions.get(reach1).data],
|
||||
[101.0]
|
||||
)
|
||||
self.assertEqual(
|
||||
[data["discharge"]
|
||||
for data in river.initial_conditions.get(reach2).data],
|
||||
[103.0]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ class AdisTSwc(AdisTS):
|
|||
for LC in POL_LC:
|
||||
reach = next((
|
||||
edge for edge in study.river.enable_edges()
|
||||
if edge.id == LC.edge
|
||||
if edge.id == LC.reach
|
||||
), None)
|
||||
if reach is None:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -935,7 +935,8 @@ class AdisTTwc(AdisTT):
|
|||
for weather_parameter in study.river.weather_parameters.lst:
|
||||
config = self._weather_files.get(weather_parameter.type)
|
||||
if (config is None or weather_parameter.reach is None
|
||||
or weather_parameter.reach.is_deleted()):
|
||||
or weather_parameter.reach.is_deleted()
|
||||
or not weather_parameter.reach.is_enable()):
|
||||
continue
|
||||
_, extension = config
|
||||
exported = self._export_weather_file(
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
val = list(
|
||||
map(
|
||||
lambda n: n.name, self._data.edges()
|
||||
lambda n: n.name, self._data.enable_edges()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
val = list(
|
||||
map(
|
||||
lambda n: n.name, self._data.edges()
|
||||
lambda n: n.name, self._data.enable_edges()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
val = []
|
||||
if self._mode == "rk":
|
||||
reach = self._data.hydraulic_structures\
|
||||
.get(index.row())\
|
||||
.get_for_enabled_reaches(index.row())\
|
||||
.input_reach
|
||||
if reach is not None:
|
||||
val = list(
|
||||
|
|
@ -73,7 +73,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
val = list(
|
||||
map(
|
||||
lambda n: n.name, self._data.edges()
|
||||
lambda n: n.name, self._data.enable_edges()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
|
||||
if self._mode == "rk":
|
||||
reach = self._data.hydraulic_structures\
|
||||
.get(index.row())\
|
||||
.get_for_enabled_reaches(index.row())\
|
||||
.input_reach
|
||||
profiles = list(
|
||||
filter(
|
||||
|
|
@ -128,20 +128,22 @@ class TableModel(PamhyrTableModel):
|
|||
self._lst = self._data._hydraulic_structures
|
||||
|
||||
def get_true_data_row(self, row):
|
||||
hs = self._lst.get(row)
|
||||
hs = self._lst.get_for_enabled_reaches(row)
|
||||
if hs is None:
|
||||
return len(self._lst.lst)
|
||||
|
||||
return next(
|
||||
map(
|
||||
lambda e: e[0],
|
||||
filter(
|
||||
lambda e: e[1] == hs,
|
||||
enumerate(self._lst._lst)
|
||||
enumerate(self._lst.lst)
|
||||
)
|
||||
), 0
|
||||
)
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self._lst)
|
||||
return len(self._lst.enabled_reaches_list)
|
||||
|
||||
def data(self, index, role):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
|
|
@ -149,16 +151,17 @@ class TableModel(PamhyrTableModel):
|
|||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
structure = self._lst.get_for_enabled_reaches(row)
|
||||
|
||||
if self._headers[column] == "name":
|
||||
return self._lst.get(row).name
|
||||
return structure.name
|
||||
elif self._headers[column] == "reach":
|
||||
n = self._lst.get(row).input_reach
|
||||
n = structure.input_reach
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n.name
|
||||
elif self._headers[column] == "rk":
|
||||
n = self._lst.get(row).input_section
|
||||
n = structure.input_section
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n.display_name()
|
||||
|
|
@ -174,6 +177,7 @@ class TableModel(PamhyrTableModel):
|
|||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
row = self.get_true_data_row(row)
|
||||
na = self._trad['not_associated']
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||
|
||||
def add(self):
|
||||
rows = self.index_selected_rows()
|
||||
if len(self._hs_lst) == 0 or len(rows) == 0:
|
||||
if len(self._hs_lst.enabled_reaches_list) == 0 or len(rows) == 0:
|
||||
self._table.add(0)
|
||||
else:
|
||||
self._table.add(rows[0])
|
||||
|
|
@ -247,7 +247,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||
def edit(self):
|
||||
rows = self.index_selected_rows()
|
||||
for row in rows:
|
||||
data = self._hs_lst.get(row)
|
||||
data = self._hs_lst.get_for_enabled_reaches(row)
|
||||
|
||||
if self.sub_window_exists(
|
||||
BasicHydraulicStructuresWindow,
|
||||
|
|
@ -269,7 +269,8 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||
self._checkbox.setChecked(True)
|
||||
else:
|
||||
self._checkbox.setEnabled(True)
|
||||
self._checkbox.setChecked(self._hs_lst.get(row).enabled)
|
||||
structure = self._hs_lst.get_for_enabled_reaches(row)
|
||||
self._checkbox.setChecked(structure.enabled)
|
||||
|
||||
def _set_structure_state(self):
|
||||
rows = self.index_selected_rows()
|
||||
|
|
@ -288,16 +289,18 @@ class HydraulicStructuresWindow(PamhyrWindow):
|
|||
def _update_clear_plot(self):
|
||||
rows = self.index_selected_rows()
|
||||
|
||||
if len(rows) == 0 or len(self._hs_lst) == 0:
|
||||
if (len(rows) == 0 or
|
||||
len(self._hs_lst.enabled_reaches_list) == 0):
|
||||
self._update_clear_all()
|
||||
return
|
||||
|
||||
reach = self._hs_lst.get(rows[0]).input_reach
|
||||
structure = self._hs_lst.get_for_enabled_reaches(rows[0])
|
||||
reach = structure.input_reach
|
||||
if reach is not None:
|
||||
self.plot_rkc.set_reach(reach)
|
||||
self.plot_ac.set_reach(reach)
|
||||
|
||||
profile = self._hs_lst.get(rows[0]).input_section
|
||||
profile = structure.input_section
|
||||
if profile is not None:
|
||||
profiles = reach.reach\
|
||||
.get_profiles_from_rk(
|
||||
|
|
|
|||
|
|
@ -55,17 +55,27 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
self._trad = trad
|
||||
self._ic_spec_lst = ic_spec_lst
|
||||
|
||||
def _specifications(self):
|
||||
if hasattr(
|
||||
self._ic_spec_lst,
|
||||
"get_specs_for_enabled_reaches"
|
||||
):
|
||||
return self._ic_spec_lst.get_specs_for_enabled_reaches(
|
||||
self._data.edges()
|
||||
)
|
||||
return self._ic_spec_lst
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
self.editor = QComboBox(parent)
|
||||
|
||||
val = []
|
||||
if self._mode == "rk":
|
||||
reach_id = self._ic_spec_lst[index.row()].reach
|
||||
reach_id = self._specifications()[index.row()].reach
|
||||
|
||||
reach = next(filter(lambda edge: edge.id == reach_id,
|
||||
self._data.edges()), None)
|
||||
|
||||
if reach_id is not None:
|
||||
if reach is not None:
|
||||
val = list(
|
||||
map(
|
||||
lambda rk: str(rk), reach.reach.get_rk()
|
||||
|
|
@ -74,7 +84,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
val = list(
|
||||
map(
|
||||
lambda n: n.name, self._data.edges()
|
||||
lambda n: n.name, self._data.enable_edges()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -117,11 +127,8 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||
self._data = data
|
||||
|
||||
def _setup_lst(self):
|
||||
self._lst = list(
|
||||
filter(
|
||||
lambda ica: ica._deleted is False,
|
||||
self._data._data
|
||||
)
|
||||
self._lst = self._data.get_specs_for_enabled_reaches(
|
||||
self._river.edges()
|
||||
)
|
||||
|
||||
def rowCount(self, parent):
|
||||
|
|
|
|||
|
|
@ -152,14 +152,14 @@ class InitialConditionsAdisTSWindow(PamhyrWindow):
|
|||
self._delegate_reach = ComboBoxDelegate(
|
||||
trad=self._trad,
|
||||
data=self._study.river,
|
||||
ic_spec_lst=self._data[0]._data,
|
||||
ic_spec_lst=self._data[0],
|
||||
parent=self,
|
||||
mode="reaches"
|
||||
)
|
||||
self._delegate_rk = ComboBoxDelegate(
|
||||
trad=self._trad,
|
||||
data=self._study.river,
|
||||
ic_spec_lst=self._data[0]._data,
|
||||
ic_spec_lst=self._data[0],
|
||||
parent=self,
|
||||
mode="rk"
|
||||
)
|
||||
|
|
@ -308,7 +308,10 @@ class InitialConditionsAdisTSWindow(PamhyrWindow):
|
|||
|
||||
def add(self):
|
||||
rows = self.index_selected_rows()
|
||||
if len(self._data[0]._data) == 0 or len(rows) == 0:
|
||||
visible = self._data[0].get_specs_for_enabled_reaches(
|
||||
self._study.river.edges()
|
||||
)
|
||||
if len(visible) == 0 or len(rows) == 0:
|
||||
self._table_spec.add(0)
|
||||
else:
|
||||
self._table_spec.add(rows[0])
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
val = list(
|
||||
map(
|
||||
lambda n: n.name, self._data.edges()
|
||||
lambda n: n.name, self._data.enable_edges()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -140,13 +140,30 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||
self._data = data
|
||||
|
||||
def _setup_lst(self):
|
||||
enabled_reach_ids = {
|
||||
reach.id
|
||||
for reach in self._river.enable_edges()
|
||||
}
|
||||
self._lst = list(
|
||||
filter(
|
||||
lambda ica: ica._deleted is False,
|
||||
lambda ica: (
|
||||
ica._deleted is False and
|
||||
(
|
||||
ica.reach in (None, -1) or
|
||||
ica.reach in enabled_reach_ids
|
||||
)
|
||||
),
|
||||
self._data._data
|
||||
)
|
||||
)
|
||||
|
||||
def refresh(self):
|
||||
self.beginResetModel()
|
||||
try:
|
||||
self._setup_lst()
|
||||
finally:
|
||||
self.endResetModel()
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self._lst)
|
||||
|
||||
|
|
@ -221,19 +238,30 @@ class InitialConditionTableModel(PamhyrTableModel):
|
|||
)
|
||||
)
|
||||
else:
|
||||
new_value = value
|
||||
if self._headers[column] == "reach":
|
||||
reach = self._river.edge(value)
|
||||
rks = reach.reach.get_rk()
|
||||
if not rks:
|
||||
return False
|
||||
new_value = (reach.id, min(rks))
|
||||
|
||||
self._undo.push(
|
||||
SetCommandSpec(
|
||||
self._lst, row, self._headers[column],
|
||||
(self._river.edge(value).id
|
||||
if self._headers[column] == "reach"
|
||||
else value
|
||||
)
|
||||
new_value
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
if self._headers[column] == "reach":
|
||||
rk_index = self.index(
|
||||
row, self._headers.index("rk")
|
||||
)
|
||||
self.dataChanged.emit(index, rk_index)
|
||||
else:
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ class SetCommandSpec(QUndoCommand):
|
|||
self._old = self._data[self._row].name
|
||||
elif self._column == "reach":
|
||||
self._old = self._data[self._row].reach
|
||||
self._old_start_rk = self._data[self._row].start_rk
|
||||
self._old_end_rk = self._data[self._row].end_rk
|
||||
elif self._column == "rk":
|
||||
self._old = self._data[self._row].start_rk
|
||||
elif self._column == "temperature":
|
||||
|
|
@ -84,6 +86,10 @@ class SetCommandSpec(QUndoCommand):
|
|||
elif column == "reach":
|
||||
_type = int
|
||||
|
||||
if column == "reach":
|
||||
self._new = _type(new_value[0])
|
||||
self._new_rk = float(new_value[1])
|
||||
else:
|
||||
self._new = _type(new_value)
|
||||
|
||||
def undo(self):
|
||||
|
|
@ -91,6 +97,8 @@ class SetCommandSpec(QUndoCommand):
|
|||
self._data[self._row].name = self._old
|
||||
elif self._column == "reach":
|
||||
self._data[self._row].reach = self._old
|
||||
self._data[self._row].start_rk = self._old_start_rk
|
||||
self._data[self._row].end_rk = self._old_end_rk
|
||||
elif self._column == "rk":
|
||||
self._data[self._row].start_rk = self._old
|
||||
self._data[self._row].end_rk = self._old
|
||||
|
|
@ -102,6 +110,8 @@ class SetCommandSpec(QUndoCommand):
|
|||
self._data[self._row].name = self._new
|
||||
elif self._column == "reach":
|
||||
self._data[self._row].reach = self._new
|
||||
self._data[self._row].start_rk = self._new_rk
|
||||
self._data[self._row].end_rk = self._new_rk
|
||||
elif self._column == "rk":
|
||||
self._data[self._row].start_rk = self._new
|
||||
self._data[self._row].end_rk = self._new
|
||||
|
|
|
|||
|
|
@ -309,3 +309,10 @@ class InitialConditionsTemperatureWindow(PamhyrWindow):
|
|||
if len(rows) == 0:
|
||||
return
|
||||
self._table_spec.delete(rows)
|
||||
|
||||
def _propagated_update(self, key=Modules(0)):
|
||||
if Modules.NETWORK not in key:
|
||||
return
|
||||
|
||||
self._table_spec.refresh()
|
||||
self.table_spec.clearSelection()
|
||||
|
|
|
|||
|
|
@ -103,7 +103,10 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
self.editor.addItems(
|
||||
[self._trad['not_associated']] +
|
||||
self._data.edges_names()
|
||||
[
|
||||
reach.name
|
||||
for reach in self._data.enable_edges()
|
||||
]
|
||||
)
|
||||
|
||||
self.editor.setCurrentText(index.data(Qt.DisplayRole))
|
||||
|
|
@ -154,7 +157,9 @@ class TableModel(PamhyrTableModel):
|
|||
self._long_types = self._trad.get_dict("long_types")
|
||||
|
||||
def get_true_data_row(self, row):
|
||||
lc = self._lst.get(self._tab, row)
|
||||
lc = self._lst.get_for_enabled_reaches(self._tab, row)
|
||||
if lc is None:
|
||||
return len(self._lst.get_tab(self._tab))
|
||||
|
||||
return next(
|
||||
map(
|
||||
|
|
@ -167,7 +172,7 @@ class TableModel(PamhyrTableModel):
|
|||
)
|
||||
|
||||
def rowCount(self, parent):
|
||||
return self._lst.len(self._tab)
|
||||
return len(self._lst.get_tab_for_enabled_reaches(self._tab))
|
||||
|
||||
def data(self, index, role):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
|
|
@ -175,21 +180,22 @@ class TableModel(PamhyrTableModel):
|
|||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
contribution = self._lst.get_for_enabled_reaches(self._tab, row)
|
||||
|
||||
if self._headers[column] == "name":
|
||||
return self._lst.get(self._tab, row).name
|
||||
return contribution.name
|
||||
elif self._headers[column] == "type":
|
||||
t = self._lst.get(self._tab, row).lctype
|
||||
t = contribution.lctype
|
||||
return self._long_types[t]
|
||||
elif self._headers[column] == "edge":
|
||||
n = self._lst.get(self._tab, row).reach
|
||||
n = contribution.reach
|
||||
if n is None:
|
||||
return self._trad['not_associated']
|
||||
return n.name
|
||||
elif self._headers[column] == "begin_rk":
|
||||
return str(self._lst.get(self._tab, row).begin_rk)
|
||||
return str(contribution.begin_rk)
|
||||
elif self._headers[column] == "end_rk":
|
||||
return str(self._lst.get(self._tab, row).end_rk)
|
||||
return str(contribution.end_rk)
|
||||
|
||||
return QVariant()
|
||||
|
||||
|
|
@ -202,6 +208,8 @@ class TableModel(PamhyrTableModel):
|
|||
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
contribution = self._lst.get_for_enabled_reaches(self._tab, row)
|
||||
row = self.get_true_data_row(row)
|
||||
|
||||
try:
|
||||
if self._headers[column] == "name":
|
||||
|
|
@ -225,7 +233,7 @@ class TableModel(PamhyrTableModel):
|
|||
)
|
||||
)
|
||||
elif self._headers[column] == "begin_rk":
|
||||
_edge = self._lst.get(self._tab, row).reach
|
||||
_edge = contribution.reach
|
||||
_begin_rk = next(
|
||||
p for p in _edge.reach.profiles
|
||||
if p.pamhyr_id == value
|
||||
|
|
@ -236,7 +244,7 @@ class TableModel(PamhyrTableModel):
|
|||
)
|
||||
)
|
||||
elif self._headers[column] == "end_rk":
|
||||
_edge = self._lst.get(self._tab, row).reach
|
||||
_edge = contribution.reach
|
||||
_end_rk = next(
|
||||
p for p in _edge.reach.profiles
|
||||
if p.pamhyr_id == value
|
||||
|
|
|
|||
|
|
@ -213,11 +213,11 @@ class LateralContributionWindow(PamhyrWindow):
|
|||
if len(rows) > 0:
|
||||
edge = self._study.river\
|
||||
.lateral_contribution\
|
||||
.get(tab, rows[0])\
|
||||
.get_for_enabled_reaches(tab, rows[0])\
|
||||
.reach
|
||||
if edge:
|
||||
data = edge.reach
|
||||
lc = self._lcs.get(tab, rows[0])
|
||||
lc = self._lcs.get_for_enabled_reaches(tab, rows[0])
|
||||
highlight = (lc.begin_rk, lc.end_rk)
|
||||
|
||||
for delegate in self._delegate_rk:
|
||||
|
|
@ -236,7 +236,8 @@ class LateralContributionWindow(PamhyrWindow):
|
|||
def add(self):
|
||||
tab = self.current_tab()
|
||||
rows = self.index_selected_rows()
|
||||
if self._lcs.len(tab) == 0 or len(rows) == 0:
|
||||
visible = self._lcs.get_tab_for_enabled_reaches(tab)
|
||||
if len(visible) == 0 or len(rows) == 0:
|
||||
self._table[tab].add(0)
|
||||
else:
|
||||
self._table[tab].add(rows[0])
|
||||
|
|
@ -291,7 +292,7 @@ class LateralContributionWindow(PamhyrWindow):
|
|||
tab = self.current_tab()
|
||||
rows = self.index_selected_rows()
|
||||
for row in rows:
|
||||
data = self._lcs.get(tab, row)
|
||||
data = self._lcs.get_for_enabled_reaches(tab, row)
|
||||
|
||||
if self.sub_window_exists(
|
||||
EditLateralContributionWindow,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,10 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
self.editor.addItems(
|
||||
[self._trad['not_associated']] +
|
||||
self._data.edges_names()
|
||||
[
|
||||
reach.name
|
||||
for reach in self._data.enable_edges()
|
||||
]
|
||||
)
|
||||
|
||||
self.editor.setCurrentText(index.data(Qt.DisplayRole))
|
||||
|
|
@ -119,6 +122,11 @@ class TableModel(PamhyrTableModel):
|
|||
self._setup_lst()
|
||||
|
||||
def _setup_lst(self):
|
||||
enabled_reach_ids = {
|
||||
reach.id
|
||||
for reach in self._data.enable_edges()
|
||||
}
|
||||
|
||||
if self._lcs_list is not None:
|
||||
self._lcs_pol_list = [
|
||||
lcs for lcs in self._lcs_list._lst
|
||||
|
|
@ -127,7 +135,13 @@ class TableModel(PamhyrTableModel):
|
|||
|
||||
self._lst = list(
|
||||
filter(
|
||||
lambda x: x._deleted is False,
|
||||
lambda x: (
|
||||
x._deleted is False and
|
||||
(
|
||||
x.reach in (None, -1) or
|
||||
x.reach in enabled_reach_ids
|
||||
)
|
||||
),
|
||||
self._lcs_pol_list
|
||||
)
|
||||
)
|
||||
|
|
@ -137,6 +151,18 @@ class TableModel(PamhyrTableModel):
|
|||
def rowCount(self, parent):
|
||||
return len(self._lst)
|
||||
|
||||
def get(self, row):
|
||||
if 0 <= row < len(self._lst):
|
||||
return self._lst[row]
|
||||
return None
|
||||
|
||||
def refresh(self):
|
||||
self.beginResetModel()
|
||||
try:
|
||||
self._setup_lst()
|
||||
finally:
|
||||
self.endResetModel()
|
||||
|
||||
def data(self, index, role):
|
||||
if role != Qt.ItemDataRole.DisplayRole:
|
||||
return QVariant()
|
||||
|
|
@ -170,11 +196,18 @@ class TableModel(PamhyrTableModel):
|
|||
|
||||
try:
|
||||
if self._headers[column] == "reach":
|
||||
reach = self._data.reach(value)
|
||||
rks = reach.reach.get_rk()
|
||||
if len(rks) == 0:
|
||||
return False
|
||||
|
||||
self._undo.push(
|
||||
SetReachCommand(
|
||||
self._lcs_list, self._lst,
|
||||
row,
|
||||
self._data.reach(value).id
|
||||
reach.id,
|
||||
min(rks),
|
||||
max(rks)
|
||||
)
|
||||
)
|
||||
elif self._headers[column] == "begin_rk":
|
||||
|
|
@ -193,6 +226,12 @@ class TableModel(PamhyrTableModel):
|
|||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
if self._headers[column] == "reach":
|
||||
end_index = self.index(
|
||||
row, self._headers.index("end_rk")
|
||||
)
|
||||
self.dataChanged.emit(index, end_index)
|
||||
else:
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -64,20 +64,30 @@ class SetEndCommand(QUndoCommand):
|
|||
|
||||
|
||||
class SetReachCommand(QUndoCommand):
|
||||
def __init__(self, lcs, lcs_lst, index, reach):
|
||||
def __init__(self, lcs, lcs_lst, index, reach, begin_rk, end_rk):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._lcs = lcs
|
||||
self._lcs_lst = lcs_lst
|
||||
self._index = index
|
||||
self._old = self._lcs_lst[self._index].reach
|
||||
self._old_begin_rk = self._lcs_lst[self._index].begin_rk
|
||||
self._old_end_rk = self._lcs_lst[self._index].end_rk
|
||||
self._new = reach
|
||||
self._new_begin_rk = begin_rk
|
||||
self._new_end_rk = end_rk
|
||||
|
||||
def undo(self):
|
||||
self._lcs_lst[self._index].reach = self._old
|
||||
contribution = self._lcs_lst[self._index]
|
||||
contribution.reach = self._old
|
||||
contribution.begin_rk = self._old_begin_rk
|
||||
contribution.end_rk = self._old_end_rk
|
||||
|
||||
def redo(self):
|
||||
self._lcs_lst[self._index].reach = self._new
|
||||
contribution = self._lcs_lst[self._index]
|
||||
contribution.reach = self._new
|
||||
contribution.begin_rk = self._new_begin_rk
|
||||
contribution.end_rk = self._new_end_rk
|
||||
|
||||
|
||||
class AddCommand(QUndoCommand):
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import logging
|
|||
|
||||
from tools import trace, timer
|
||||
|
||||
from Modules import Modules
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
|
||||
from PyQt5.QtGui import (
|
||||
|
|
@ -187,12 +188,13 @@ class LateralContributionAdisTSWindow(PamhyrWindow):
|
|||
data = None
|
||||
highlight = None
|
||||
|
||||
tab = "liquid"
|
||||
|
||||
if len(rows) > 0:
|
||||
reach_id = self._study.river\
|
||||
.lateral_contributions_adists.lst[rows[0]]\
|
||||
.reach
|
||||
contribution = self._table.get(rows[0])
|
||||
reach_id = (
|
||||
contribution.reach
|
||||
if contribution is not None
|
||||
else None
|
||||
)
|
||||
|
||||
if reach_id:
|
||||
reach = next(
|
||||
|
|
@ -201,8 +203,10 @@ class LateralContributionAdisTSWindow(PamhyrWindow):
|
|||
self._study.river.reachs()))
|
||||
|
||||
data = reach.reach
|
||||
lc = self._lcs.lst[rows[0]]
|
||||
highlight = (lc.begin_rk, lc.end_rk)
|
||||
highlight = (
|
||||
contribution.begin_rk,
|
||||
contribution.end_rk
|
||||
)
|
||||
|
||||
for delegate in self._delegate_rk:
|
||||
delegate.data = reach
|
||||
|
|
@ -254,13 +258,23 @@ class LateralContributionAdisTSWindow(PamhyrWindow):
|
|||
self._table.redo()
|
||||
self._set_current_reach()
|
||||
|
||||
def _propagated_update(self, key=Modules(0)):
|
||||
if Modules.NETWORK not in key:
|
||||
return
|
||||
|
||||
self._table.refresh()
|
||||
self.find(QTableView, "tableView").clearSelection()
|
||||
self._set_current_reach()
|
||||
|
||||
def edit(self):
|
||||
rows = self.index_selected_rows()
|
||||
if not rows:
|
||||
return
|
||||
|
||||
for row in rows:
|
||||
data = self._lcs.lst[row]
|
||||
data = self._table.get(row)
|
||||
if data is None:
|
||||
continue
|
||||
|
||||
if self.sub_window_exists(
|
||||
EditLateralContributionAdisTSWindow,
|
||||
|
|
|
|||
|
|
@ -1526,6 +1526,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||
sl.show()
|
||||
|
||||
def open_reach_sediment_layers(self):
|
||||
if self._study is None:
|
||||
logger.debug(
|
||||
"No study open for reach sediment layers edition..."
|
||||
)
|
||||
return
|
||||
|
||||
if not self._study.river.has_current_reach():
|
||||
self.msg_select_reach()
|
||||
return
|
||||
|
||||
reach = self._study.river.current_reach().reach
|
||||
|
||||
if self.sub_window_exists(
|
||||
|
|
@ -2307,11 +2317,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
|||
logger.debug("No study open for sql debuging...")
|
||||
return
|
||||
|
||||
# todo : gérer le cas où le dossier a un espace dans le nom
|
||||
# (ne veut pas ouvrir sqlitebrowser)
|
||||
|
||||
file = self._study.filename
|
||||
_ = subprocess.Popen(
|
||||
f"sqlitebrowser {file}",
|
||||
shell=True
|
||||
["sqlitebrowser", file]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,10 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
else:
|
||||
self.editor.addItems(
|
||||
[self._trad['not_associated']] +
|
||||
self._data.edges_names()
|
||||
[
|
||||
reach.name
|
||||
for reach in self._data.enable_edges()
|
||||
]
|
||||
)
|
||||
|
||||
self.editor.setCurrentText(str(index.data(Qt.DisplayRole)))
|
||||
|
|
@ -144,8 +147,28 @@ class WeatherParametersTableModel(PamhyrTableModel):
|
|||
if self._type == "ND" or self._data is None:
|
||||
self._lst = []
|
||||
return
|
||||
enabled_reach_ids = {
|
||||
reach.id
|
||||
for reach in self._river.enable_edges()
|
||||
}
|
||||
self._lst = self._data.lst
|
||||
self._lst = list(filter(lambda wp: wp.type == self._type, self._lst))
|
||||
self._lst = list(filter(
|
||||
lambda wp: (
|
||||
wp.type == self._type and
|
||||
(
|
||||
wp.reach is None or
|
||||
wp.reach.id in enabled_reach_ids
|
||||
)
|
||||
),
|
||||
self._lst
|
||||
))
|
||||
|
||||
def refresh(self):
|
||||
self.beginResetModel()
|
||||
try:
|
||||
self._setup_lst()
|
||||
finally:
|
||||
self.endResetModel()
|
||||
|
||||
def update_tab_spec(self, type="ND", enabled=True):
|
||||
if enabled:
|
||||
|
|
@ -239,15 +262,24 @@ class WeatherParametersTableModel(PamhyrTableModel):
|
|||
)
|
||||
)
|
||||
elif self._headers[column] == "reach":
|
||||
edge = self._river.edge(value)
|
||||
if not edge.reach.profiles:
|
||||
return False
|
||||
self._undo.push(
|
||||
SetEdgeCommand(
|
||||
self._data, global_row, self._river.edge(value)
|
||||
self._data, global_row, edge
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
if self._headers[column] == "reach":
|
||||
end_index = self.index(
|
||||
row, self._headers.index("end_rk")
|
||||
)
|
||||
self.dataChanged.emit(index, end_index)
|
||||
else:
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -125,14 +125,26 @@ class SetEdgeCommand(QUndoCommand):
|
|||
|
||||
self._wps = wps
|
||||
self._index = index
|
||||
self._old = self._wps.get(self._index).reach
|
||||
weather_parameter = self._wps.get(self._index)
|
||||
self._old = weather_parameter.reach
|
||||
self._old_begin = weather_parameter.begin_section
|
||||
self._old_end = weather_parameter.end_section
|
||||
self._new = edge
|
||||
profiles = edge.reach.profiles
|
||||
self._new_begin = min(profiles, key=lambda profile: profile.rk)
|
||||
self._new_end = max(profiles, key=lambda profile: profile.rk)
|
||||
|
||||
def undo(self):
|
||||
self._wps.get(self._index).reach = self._old
|
||||
weather_parameter = self._wps.get(self._index)
|
||||
weather_parameter.reach = self._old
|
||||
weather_parameter.begin_section = self._old_begin
|
||||
weather_parameter.end_section = self._old_end
|
||||
|
||||
def redo(self):
|
||||
self._wps.get(self._index).reach = self._new
|
||||
weather_parameter = self._wps.get(self._index)
|
||||
weather_parameter.reach = self._new
|
||||
weather_parameter.begin_section = self._new_begin
|
||||
weather_parameter.end_section = self._new_end
|
||||
|
||||
|
||||
class AddCommand(QUndoCommand):
|
||||
|
|
|
|||
|
|
@ -439,3 +439,10 @@ class WeatherParametersWindow(PamhyrWindow):
|
|||
parent=self
|
||||
)
|
||||
win.show()
|
||||
|
||||
def _propagated_update(self, key=Modules(0)):
|
||||
if Modules.NETWORK not in key:
|
||||
return
|
||||
|
||||
self._table_spec.refresh()
|
||||
self.table_spec.clearSelection()
|
||||
|
|
|
|||
Loading…
Reference in New Issue