Compare commits

..

No commits in common. "4d20c2457a667493bfdd472b6470f7103db842d8" and "084c22836b3538d3d2861c958f72f774de606e3b" have entirely different histories.

19 changed files with 2443 additions and 2547 deletions

View File

@ -157,12 +157,12 @@
%% %%
%% FIXME: Delete me for the first realease %% FIXME: Delete me for the first realease
%% \usepackage{draftwatermark} \usepackage{draftwatermark}
%% \SetWatermarkLightness{0.8} \SetWatermarkLightness{0.8}
%% \SetWatermarkAngle{25} \SetWatermarkAngle{25}
%% \SetWatermarkScale{3} \SetWatermarkScale{3}
%% \SetWatermarkFontSize{1cm} \SetWatermarkFontSize{1cm}
%% \SetWatermarkText{Work in progress} \SetWatermarkText{Work in progress}
%% Icons %% Icons

View File

@ -514,42 +514,6 @@ class BoundaryCondition(SQLSubModel):
self._sigma = float(value) self._sigma = float(value)
self.modified() self.modified()
@property
def d50(self):
return self._d50
@d50.setter
def d50(self, value):
self._d50 = float(value)
self.modified()
@property
def sigma(self):
return self._sigma
@sigma.setter
def sigma(self, value):
self._sigma = float(value)
self.modified()
@property
def d50(self):
return self._d50
@d50.setter
def d50(self, value):
self._d50 = float(value)
self.modified()
@property
def sigma(self):
return self._sigma
@sigma.setter
def sigma(self, value):
self._sigma = float(value)
self.modified()
@property @property
def header(self): def header(self):
return self._header.copy() return self._header.copy()

View File

@ -71,7 +71,7 @@ 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 major == "0" and int(minor) <= 1:
if int(release) < 7: if int(release) < 7:
cls._db_create(execute) cls._db_create(execute)
created = True created = True
@ -249,7 +249,7 @@ 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) <= 1:
if int(release) < 7: if int(release) < 7:
cls._db_create(execute) cls._db_create(execute)
created = True created = True

View File

@ -274,9 +274,6 @@ class HydraulicStructure(SQLSubModel):
return hs return hs
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
if not self.must_be_saved():
return True
execute( execute(
"DELETE FROM hydraulic_structures " + "DELETE FROM hydraulic_structures " +
f"WHERE pamhyr_id = {self.pamhyr_id} " + f"WHERE pamhyr_id = {self.pamhyr_id} " +

View File

@ -225,8 +225,6 @@ 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
ind = data["ind"] ind = data["ind"]
execute( execute(
@ -398,7 +396,7 @@ class InitialConditions(SQLSubModel):
@reach.setter @reach.setter
def reach(self, new): def reach(self, new):
self._reach = new self._reach = reach
self.modified() self.modified()
@property @property

View File

@ -147,9 +147,9 @@ class Data(SQLSubModel):
it = iter(v) it = iter(v)
pid = next(it) pid = next(it)
deleted = next(it) delete = next(it)
data0 = lc._types[0](next(it)) data0 = bc._types[0](next(it))
data1 = lc._types[1](next(it)) data1 = bc._types[1](next(it))
owner_scenario = next(it) owner_scenario = next(it)
nd = cls( nd = cls(

View File

@ -278,10 +278,8 @@ class PollutantCharacteristics(SQLSubModel):
class Pollutants(SQLSubModel): class Pollutants(SQLSubModel):
_sub_classes = [ _sub_classes = [PollutantCharacteristics,
PollutantCharacteristics, BoundaryConditionAdisTS]
# BoundaryConditionAdisTS
]
def __init__(self, id: int = -1, name: str = "", def __init__(self, id: int = -1, name: str = "",
status=None, owner_scenario=-1): status=None, owner_scenario=-1):
@ -402,7 +400,7 @@ class Pollutants(SQLSubModel):
return new return new
table = execute( table = execute(
"SELECT pamhyr_id, deleted, name, scenario FROM pollutants " + "SELECT pamhyr_id, deleted, name FROM pollutants " +
f"WHERE scenario = {scenario.id} " + f"WHERE scenario = {scenario.id} " +
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})" f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
) )
@ -414,12 +412,10 @@ class Pollutants(SQLSubModel):
pid = next(it) pid = next(it)
deleted = (next(it) == 1) deleted = (next(it) == 1)
name = next(it) name = next(it)
owner_scenario = next(it)
new_pollutant = cls( new_pollutant = cls(
id=pid, name=name, id=pid, name=name,
status=status, status=status
owner_scenario=owner_scenario
) )
if deleted: if deleted:
new_pollutant.set_as_deleted() new_pollutant.set_as_deleted()

View File

@ -180,9 +180,6 @@ class RiverNode(Node):
return nodes return nodes
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
if not self.must_be_saved():
return True
execute( execute(
"INSERT OR REPLACE INTO river_node(" + "INSERT OR REPLACE INTO river_node(" +
"pamhyr_id, deleted, name, x, y, scenario" + "pamhyr_id, deleted, name, x, y, scenario" +
@ -364,7 +361,7 @@ class RiverReach(Edge):
) )
new.enable(enable=enabled) new.enable(enable=enabled)
if deleted: if deleted:
new.set_as_deleted() nd.set_as_deleted()
data["reach"] = new data["reach"] = new
new._reach = Reach._db_load(execute, data) new._reach = Reach._db_load(execute, data)
@ -380,9 +377,6 @@ class RiverReach(Edge):
return reachs return reachs
def _db_save(self, execute, data=None): def _db_save(self, execute, data=None):
if not self.must_be_saved():
return True
execute( execute(
"INSERT OR REPLACE INTO " + "INSERT OR REPLACE INTO " +
"river_reach(" + "river_reach(" +
@ -392,7 +386,7 @@ class RiverReach(Edge):
"VALUES (" + "VALUES (" +
f"{self.pamhyr_id}, {self._db_format(self.is_deleted())}, " + f"{self.pamhyr_id}, {self._db_format(self.is_deleted())}, " +
f"'{self._db_format(self._name)}', " + f"'{self._db_format(self._name)}', " +
f"{self._db_format(self.is_enable())}," + f"{self._db_format(self.is_enable())},"
f"{self.node1.pamhyr_id}, {self.node2.pamhyr_id}, " + f"{self.node1.pamhyr_id}, {self.node2.pamhyr_id}, " +
f"{self._status.scenario_id}" + f"{self._status.scenario_id}" +
")" ")"
@ -549,7 +543,7 @@ class River(Graph):
new._nodes = RiverNode._db_load( new._nodes = RiverNode._db_load(
execute, data execute, data
) )
data["nodes"] = new._nodes data["nodes"] = new.nodes()
data['loaded_pid'] = set() data['loaded_pid'] = set()
new._edges = RiverReach._db_load( new._edges = RiverReach._db_load(

View File

@ -17,51 +17,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import logging
from tools import logger_exception from tools import logger_exception
from Model.Tools.PamhyrDB import SQLSubModel from Model.Tools.PamhyrDB import SQLSubModel
logger = logging.getLogger()
class Scenario(SQLSubModel): class Scenario(SQLSubModel):
_id_cnt = 0 _id_cnt = 0
_sub_classes = [] _sub_classes = []
tables_with_deleted_column = [
# Adists
"output_rk_adists",
"boundary_condition_adists", "boundary_condition_data_adists",
"lateral_contribution_adists", "lateral_contribution_data_adists",
"initial_conditions_adists", "initial_conditions_adists_data",
"d90_adists", "d90_adists_spec",
"dif_adists_spec",
"pollutants", "pollutants_characteristics",
# Hydraulic
"additional_files",
"boundary_condition", "boundary_condition_data",
"lateral_contribution", "lateral_contribution_data",
"friction", "stricklers",
"hydraulic_structures",
"hydraulic_structures_basic",
"initial_conditions",
"sedimentary_layer", "sedimentary_layer_layer",
"reservoir", "reservoir_data",
"rep_lines",
"geometry_pointXYZ", "geometry_profileXYZ",
"river_reach", "river_node",
"geotiff", "reservoir", "reservoir_data",
]
related_tables = tables_with_deleted_column + [
"dif_adists",
"solver_parameter",
"hydraulic_structures_basic_value",
"results", "results_data", "results_add_data",
]
def __init__(self, def __init__(self,
id: int = -1, id: int = -1,
name: str = "", name: str = "",
@ -206,7 +171,29 @@ class Scenario(SQLSubModel):
def drop_all(self, execute): def drop_all(self, execute):
execute(f"DELETE FROM scenario WHERE id = {self.id}") execute(f"DELETE FROM scenario WHERE id = {self.id}")
tables = self.related_tables tables = [
# Adists
"output_rk_adists",
"boundary_condition_adists", "boundary_condition_data_adists",
"lateral_contribution_adists", "lateral_contribution_data_adists",
"initial_conditions_adists",
"d90_adists", "dif_adists",
"pollutants", "pollutants_characteristics",
# Hydraulic
"additional_files",
"boundary_condition", "boundary_condition_data",
"lateral_contribution", "lateral_contribution_data",
"friction", "stricklers",
"hydraulic_structures",
"hydraulic_structures_basic", "hydraulic_structures_basic_value",
"initial_conditions",
"sedimentary_layer", "sedimentary_layer_layer",
"reservoir", "reservoir_data",
"rep_lines",
"solver_parameter",
"geometry_pointXYZ", "geometry_profileXYZ",
"river_reach", "river_node",
]
for table in tables: for table in tables:
execute( execute(
@ -216,58 +203,6 @@ class Scenario(SQLSubModel):
return True return True
def get_parent_branch(self):
def aux(scenario, acc):
if scenario is None:
return acc
return aux(scenario.parent, [scenario.id] + acc)
return aux(self, [])
def drop_deleted_data(self, execute):
tables = self.tables_with_deleted_column
branch = self.get_parent_branch()
for table in tables:
if self.parent is None:
# This scenario is the default scenario, so we can
# delete all data marked as deleted
execute(
f"DELETE FROM {table} " +
f"WHERE scenario = {self.id} " +
"AND deleted = TRUE"
)
continue
# Select pamhyr_id for each deleted data in this scenario
# who do not exists into parents scenarios
ids = execute(
f"""
SELECT pamhyr_id FROM {table}
WHERE deleted = TRUE
AND scenario = {self.id}
AND pamhyr_id NOT IN (
SELECT pamhyr_id FROM {table}
WHERE scenario IN
({', '.join(map(str, branch[:-1]))})
)
""", fetch_one=False
)
if ids is None or len(ids) == 0:
continue
logger.debug(
f"(s{self.id}) Drop deleted data into '{table}' : {ids}"
)
execute(
f"DELETE FROM {table} " +
f"WHERE scenario = {self.id} " +
"AND pamhyr_id IN " +
f"({', '.join(map(lambda x: str(x[0]), ids))})"
)
@property @property
def id(self): def id(self):
return self._id return self._id

View File

@ -449,13 +449,6 @@ class Study(SQLModel):
[self.scenarios, self._river], [self.scenarios, self._river],
data=progress data=progress
) )
# Clear DB for each scenarios
for scenar in self.scenarios.lst:
scenar.drop_deleted_data(self.execute)
progress()
self.commit() self.commit()
def sql_save_request_count(self, *args, **kargs): def sql_save_request_count(self, *args, **kargs):
@ -466,7 +459,7 @@ class Study(SQLModel):
[self.scenarios, self._river] [self.scenarios, self._river]
) )
logger.debug(cnt) logger.debug(cnt)
return cnt + 8 return cnt + 7
def close(self): def close(self):
"""Close db connection """Close db connection
@ -525,8 +518,7 @@ class Study(SQLModel):
data["study"] = self data["study"] = self
river._db_load_results(sql_exec, data=data) river._db_load_results(sql_exec, data=data)
# FIXME: Disable scenario cache to save memory usage self._river_scenario_cache[scenario] = river
# self._river_scenario_cache[scenario] = river
self.status.scenario = old_scenario self.status.scenario = old_scenario
return river return river

View File

@ -793,7 +793,6 @@ class AdisTSwc(AdisTS):
for file_bin in path_files: for file_bin in path_files:
key_pol = os.path.basename(file_bin)[0:-4] key_pol = os.path.basename(file_bin)[0:-4]
data_tmp[key_pol] = {} data_tmp[key_pol] = {}
logger.info(f"read_bin: Start reading '{file_bin}' ...")
with open(file_bin, 'rb') as f: with open(file_bin, 'rb') as f:
# header # header
# first line # first line
@ -845,9 +844,7 @@ class AdisTSwc(AdisTS):
# seventh line (useless) # seventh line (useless)
for k in range(0, ismax, kbl): for k in range(0, ismax, kbl):
data = np.fromfile(f, dtype=np.int32, count=1) # (start) data = np.fromfile(f, dtype=np.int32, count=1) # (start)
zero = np.fromfile( zero = np.fromfile(f, dtype=np.int32, count=ismax)
f, dtype=np.int32, count=min(k + kbl, ismax) - k
)
data = np.fromfile(f, dtype=np.int32, count=1) # (end) data = np.fromfile(f, dtype=np.int32, count=1) # (end)
# end header # end header
# data # data
@ -878,6 +875,7 @@ class AdisTSwc(AdisTS):
for r, reach in enumerate(reachs): for r, reach in enumerate(reachs):
for i in range(is1[r]-1, is2[r]): for i in range(is1[r]-1, is2[r]):
p_i = ip_to_ri(reach, i) p_i = ip_to_ri(reach, i)
for t_data in timestamps_keys: for t_data in timestamps_keys:
pol_view = [] pol_view = []
for pol in pollutants_keys: for pol in pollutants_keys:

View File

@ -19,7 +19,6 @@
import os import os
import logging import logging
import numpy as np import numpy as np
import time
from functools import reduce from functools import reduce
from itertools import chain from itertools import chain
@ -327,7 +326,7 @@ class Mage(CommandLineSolver):
v0 = d[0] v0 = d[0]
v1 = d[1] v1 = d[1]
if t in ["HYD", "LIM"]: if t in ["HYD", "QSO", "LIM"]:
v0 /= 60 # Convert first column to minute v0 /= 60 # Convert first column to minute
f.write(f"{v0:9} {v1:9} \n") f.write(f"{v0:9} {v1:9} \n")
@ -990,7 +989,7 @@ class Mage8(Mage):
# Data # Data
for d in bound.data: for d in bound.data:
f.write(f"{d[0]/60:10.3f}{d[1]:10.3f}\n") f.write(f"{d[0]:10.3f}{d[1]:10.3f}\n")
return files return files
@ -1037,7 +1036,6 @@ class Mage8(Mage):
@timer @timer
def read_bin(self, study, fname, results, qlog=None, name="0"): def read_bin(self, study, fname, results, qlog=None, name="0"):
logger.info(f"read_bin: Start reading '{fname}' ...") logger.info(f"read_bin: Start reading '{fname}' ...")
start = time.time()
with mage_file_open(fname, "r") as f: with mage_file_open(fname, "r") as f:
def newline(): return np.fromfile(f, dtype=np.int32, count=1) def newline(): return np.fromfile(f, dtype=np.int32, count=1)
@ -1184,6 +1182,7 @@ class Mage8(Mage):
logger.info(f"compute tab...") logger.info(f"compute tab...")
for r in reachs: for r in reachs:
for p in r.profiles: for p in r.profiles:
if not p.geometry.tab_up_to_date:
p.geometry.compute_tabulation() p.geometry.compute_tabulation()
logger.info(f"compute velocily...") logger.info(f"compute velocily...")
@ -1201,7 +1200,6 @@ class Mage8(Mage):
results.bufferize("Z") results.bufferize("Z")
results.bufferize("Q") results.bufferize("Q")
results.bufferize("V") results.bufferize("V")
logger.info(f"reading time: '{time.time() - start}'")
@timer @timer
def read_gra(self, study, repertory, results, qlog=None, name="0"): def read_gra(self, study, repertory, results, qlog=None, name="0"):
@ -1210,7 +1208,6 @@ class Mage8(Mage):
fname = os.path.join(repertory, f"{name}.GRA") fname = os.path.join(repertory, f"{name}.GRA")
logger.info(f"read_gra: Start reading '{fname}' ...") logger.info(f"read_gra: Start reading '{fname}' ...")
start = time.time()
with mage_file_open(fname, "r") as f: with mage_file_open(fname, "r") as f:
def newline(): return np.fromfile(f, dtype=np.int32, count=1) def newline(): return np.fromfile(f, dtype=np.int32, count=1)
@ -1406,7 +1403,6 @@ class Mage8(Mage):
results.set("sediment_timestamps", ts) results.set("sediment_timestamps", ts)
logger.info(f"read_gra: ... end with {len(ts)} timestamp read") logger.info(f"read_gra: ... end with {len(ts)} timestamp read")
logger.debug(f"reading time: '{time.time() - start}'")
@timer @timer
def results(self, study, repertory, def results(self, study, repertory,

View File

@ -55,7 +55,7 @@ class AboutWindow(PamhyrDialog):
label = self.get_label_text("label_version") label = self.get_label_text("label_version")
label = label.replace("@version", version) label = label.replace("@version", version)
label = label.replace("@codename", "") label = label.replace("@codename", "(Adis-TS)")
self.set_label_text("label_version", label) self.set_label_text("label_version", label)
# Authors # Authors

View File

@ -19,8 +19,6 @@
from View.Tools.PamhyrWindow import PamhyrDialog from View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtWidgets import QDoubleSpinBox from PyQt5.QtWidgets import QDoubleSpinBox
from View.Tools.FlexibleDoubleSpinBox import FlexibleDoubleSpinBox from View.Tools.FlexibleDoubleSpinBox import FlexibleDoubleSpinBox
from PyQt5.QtWidgets import QDoubleSpinBox
from View.Tools.FlexibleDoubleSpinBox import FlexibleDoubleSpinBox
class ShiftDialog(PamhyrDialog): class ShiftDialog(PamhyrDialog):

View File

@ -173,7 +173,7 @@ class InitialConditionTableModel(PamhyrTableModel):
def add(self, row, parent=QModelIndex()): def add(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1) self.beginInsertRows(parent, row, row - 1)
# row = self.get_true_data_row(row) row = self.get_true_data_row(row)
self._undo.push( self._undo.push(
AddCommand( AddCommand(

View File

@ -156,7 +156,7 @@ class DelCommand(QUndoCommand):
el.set_as_not_deleted() el.set_as_not_deleted()
def redo(self): def redo(self):
for el in self._lc: for el in self._bc:
el.set_as_deleted() el.set_as_deleted()

View File

@ -23,6 +23,7 @@ from PyQt5.QtWidgets import QDoubleSpinBox
class FlexibleDoubleSpinBox(QDoubleSpinBox): class FlexibleDoubleSpinBox(QDoubleSpinBox):
def keyPressEvent(self, event): def keyPressEvent(self, event):
if event.text() == ".": if event.text() == ".":
# Simule une virgule à la place du point # Simule une virgule à la place du point

View File

@ -225,7 +225,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>&lt;a href=&quot;https://gitlab.com/pamhyr/pamhyr2&quot;&gt;Source code&lt;/a&gt;</string> <string>&lt;a href=&quot;https://gitlab.irstea.fr/theophile.terraz/pamhyr&quot;&gt;Source code&lt;/a&gt;</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::RichText</enum> <enum>Qt::RichText</enum>

File diff suppressed because it is too large Load Diff