mirror of https://gitlab.com/pamhyr/pamhyr2
Results: Prepare result save.
parent
9c69f2ce6d
commit
3a3c4d9d73
|
|
@ -14,7 +14,9 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import struct
|
||||||
import logging
|
import logging
|
||||||
|
import itertools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
@ -28,12 +30,10 @@ logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class Results(SQLSubModel):
|
class Results(SQLSubModel):
|
||||||
_SQL_TABLE = "solver_results"
|
def __init__(self, id=-1, study=None, solver=None,
|
||||||
|
|
||||||
def __init__(self, study=None, solver=None,
|
|
||||||
repertory="", name="0"):
|
repertory="", name="0"):
|
||||||
super(Results, self).__init__(
|
super(Results, self).__init__(
|
||||||
status=study.status,
|
id=id, status=study.status,
|
||||||
owner_scenario=study.status.scenario.id
|
owner_scenario=study.status.scenario.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -78,3 +78,122 @@ class Results(SQLSubModel):
|
||||||
self._repertory,
|
self._repertory,
|
||||||
qlog=None,
|
qlog=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def timestamps_to_struct(self):
|
||||||
|
ts = self._meta_data["timestamps"]
|
||||||
|
sf = ">" + ''.join(itertools.repeat("d", len(ts)))
|
||||||
|
|
||||||
|
return struct.pack(sf, ts)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute, ext=""):
|
||||||
|
execute(f"""
|
||||||
|
CREATE TABLE results{ext} (
|
||||||
|
{cls.create_db_add_pamhyr_id()},
|
||||||
|
solver TEXT NOT NULL,
|
||||||
|
study_revision INTEGER NOT NULL,
|
||||||
|
creation_data DATE NOT NULL,
|
||||||
|
nb_timestamps INTEGER NOT NULL,
|
||||||
|
timestamps BLOB NOT NULL,
|
||||||
|
{Scenario.create_db_add_scenario()},
|
||||||
|
{Scenario.create_db_add_scenario_fk()},
|
||||||
|
PRIMARY KEY(pamhyr_id, scenario)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version, data=None):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
|
||||||
|
if major == "0" and int(minor) <= 2:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return cls._update_submodel(execute, version, data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
study = data['study']
|
||||||
|
status = data['status']
|
||||||
|
scenario = data["scenario"]
|
||||||
|
loaded = data['loaded_pid']
|
||||||
|
|
||||||
|
values = execute(
|
||||||
|
"SELECT pamhyr_id, solver_name, solver_type, " +
|
||||||
|
"study_revision, creation_data, nb_timestamps, timestamps, " +
|
||||||
|
"scenario " +
|
||||||
|
"FROM results " +
|
||||||
|
f"WHERE scenario = {scenario.id} " +
|
||||||
|
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))}) " +
|
||||||
|
"ORDER BY ind ASC"
|
||||||
|
)
|
||||||
|
|
||||||
|
for v in values:
|
||||||
|
it = iter(v)
|
||||||
|
|
||||||
|
pid = next(it)
|
||||||
|
solver = next(it)
|
||||||
|
revision = next(it)
|
||||||
|
creation_date = next(it)
|
||||||
|
nb_timestamps = next(it)
|
||||||
|
timestamps_bytes = next(it)
|
||||||
|
owner_scenario = next(it)
|
||||||
|
|
||||||
|
new_results = cls(
|
||||||
|
id=pid, status=status,
|
||||||
|
owner_scenario=owner_scenario
|
||||||
|
)
|
||||||
|
new_results.set("solver_name", solver_name)
|
||||||
|
new_results.set("solver_type", solver_type)
|
||||||
|
new_results.set("study_revision", revision)
|
||||||
|
new_results.set("creation_date", creation_date)
|
||||||
|
|
||||||
|
sf = ">" + ''.join(itertools.repeat("d", len(nb_timestamps)))
|
||||||
|
ts = struct.unpack(sf, timestamp_bytes)
|
||||||
|
new_results.set("timestamps", ts)
|
||||||
|
|
||||||
|
new_results._river = River._db_load(execute, data)
|
||||||
|
|
||||||
|
loaded.add(pid)
|
||||||
|
new.append(new_results)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
execute(
|
||||||
|
"DELETED FROM results " +
|
||||||
|
f"WHERE scenario = {self._owner_scenario}"
|
||||||
|
)
|
||||||
|
execute(
|
||||||
|
"DELETED FROM results_data " +
|
||||||
|
f"WHERE scenario = {self._owner_scenario}"
|
||||||
|
)
|
||||||
|
|
||||||
|
pid = self._pamhyr_id
|
||||||
|
if self._solver is None:
|
||||||
|
solver_name = self.get("solver_name")
|
||||||
|
solver_type = self.get("solver_type")
|
||||||
|
else:
|
||||||
|
solver_name = self._solver._name
|
||||||
|
solver_type = self._solver._type
|
||||||
|
|
||||||
|
ts = self.get("timestamps")
|
||||||
|
sf = ">" + ''.join(itertools.repeat("d", len(ts)))
|
||||||
|
|
||||||
|
execute(
|
||||||
|
"INSERT INTO " +
|
||||||
|
"results (pamhyr_id, solver_name, solver_type, " +
|
||||||
|
"study_revision, creation_data, nb_timestamps, timestamps, " +
|
||||||
|
"scenario) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
self._pamhyr_id, solver_name, solver_type,
|
||||||
|
self._owner_scenario.revision, self.get("creation_data"),
|
||||||
|
len(ts), struct.pack(sf, ts), self._owner_scenario
|
||||||
|
)
|
||||||
|
|
||||||
|
data["result"] = self._pamhyr_id
|
||||||
|
self._river._db_save(execute, data)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,25 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import struct
|
||||||
import logging
|
import logging
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from Model.Tools.PamhyrDB import SQLSubModel
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class Profile(object):
|
class Profile(SQLSubModel):
|
||||||
def __init__(self, profile, study):
|
def __init__(self, profile, study):
|
||||||
|
super(Profile, self).__init__(
|
||||||
|
id=-1, status=study.status,
|
||||||
|
owner_scenario=study.status.scenario.id
|
||||||
|
)
|
||||||
|
|
||||||
self._study = study
|
self._study = study
|
||||||
self._profile = profile # Source profile in the study
|
self._profile = profile # Source profile in the study
|
||||||
self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
|
self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
|
||||||
|
|
@ -65,9 +75,122 @@ class Profile(object):
|
||||||
def has_sediment(self):
|
def has_sediment(self):
|
||||||
return any(map(lambda ts: "sl" in self._data[ts], self._data))
|
return any(map(lambda ts: "sl" in self._data[ts], self._data))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute, ext=""):
|
||||||
|
execute(f"""
|
||||||
|
CREATE TABLE results_data{ext}(
|
||||||
|
{cls.create_db_add_pamhyr_id()},
|
||||||
|
result INTEGER NOT NULL,
|
||||||
|
key TEXT NOT NULL,
|
||||||
|
reach INTEGER NOT NULL,
|
||||||
|
section INTEGER NOT NULL,
|
||||||
|
len_data INTEGER NOT NULL,
|
||||||
|
data BLOB NOT NULL,
|
||||||
|
{Scenario.create_db_add_scenario()},
|
||||||
|
{Scenario.create_db_add_scenario_fk()},
|
||||||
|
FOREIGN KEY(result) REFERENCES results(pamhyr_id),
|
||||||
|
FOREIGN KEY(reach) REFERENCES river_reach(pamhyr_id),
|
||||||
|
FOREIGN KEY(section)
|
||||||
|
REFERENCES geometry_profileXYZ(pamhyr_id),
|
||||||
|
PRIMARY KEY(pamhyr_id, result, key, scenario)
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
class Reach(object):
|
if ext == "_tmp":
|
||||||
|
return True
|
||||||
|
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version, data=None):
|
||||||
|
major, minor, release = version.strip().split(".")
|
||||||
|
|
||||||
|
if major == "0" and int(minor) <= 2:
|
||||||
|
cls._db_create(execute)
|
||||||
|
|
||||||
|
return cls._update_submodel(execute, version, data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
new = []
|
||||||
|
|
||||||
|
study = data['study']
|
||||||
|
status = data['status']
|
||||||
|
scenario = data["scenario"]
|
||||||
|
loaded = data['loaded_pid']
|
||||||
|
timestamps = data['timestamps']
|
||||||
|
|
||||||
|
values = execute(
|
||||||
|
"SELECT pamhyr_id, result, key, " +
|
||||||
|
"reach, section, len_data, data, scenario " +
|
||||||
|
"FROM results_data " +
|
||||||
|
f"WHERE scenario = {scenario.id} " +
|
||||||
|
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
|
||||||
|
)
|
||||||
|
|
||||||
|
for v in values:
|
||||||
|
it = iter(v)
|
||||||
|
|
||||||
|
pid = next(it)
|
||||||
|
result = next(it)
|
||||||
|
key = next(it)
|
||||||
|
reach = next(it)
|
||||||
|
section = next(it)
|
||||||
|
len_data = next(it)
|
||||||
|
data = next(it)
|
||||||
|
owner_scenario = next(it)
|
||||||
|
|
||||||
|
new_data = cls(
|
||||||
|
id=pid, status=status,
|
||||||
|
owner_scenario=owner_scenario
|
||||||
|
)
|
||||||
|
|
||||||
|
sf = ">" + ''.join(itertools.repeat("f", len_data))
|
||||||
|
values = struct.unpack(sf, data)
|
||||||
|
|
||||||
|
for timestamp, value in zip(timestamps, values):
|
||||||
|
new_data.set(timestamp, key, value)
|
||||||
|
|
||||||
|
loaded.add(pid)
|
||||||
|
new.append(new_data)
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
def get_keys(self):
|
||||||
|
return reduce(
|
||||||
|
lambda acc, ts: acc.union(d[ts].keys())
|
||||||
|
)
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
pid = self._pamhyr_id
|
||||||
|
result = data["result"]
|
||||||
|
|
||||||
|
for key in self.get_keys():
|
||||||
|
data = self.get_key(key)
|
||||||
|
|
||||||
|
sf = ">" + ''.join(itertools.repeat("f", len(data)))
|
||||||
|
data_bytes = struct.pack(sf, data)
|
||||||
|
|
||||||
|
execute(
|
||||||
|
"INSERT INTO " +
|
||||||
|
"results_data (pamhyr_id, result, , " +
|
||||||
|
"study_revision, key, len_data, data, " +
|
||||||
|
"scenario) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
pid, result, self._owner_scenario.revision,
|
||||||
|
key, len(data), data_bytes,
|
||||||
|
self._owner_scenario
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class Reach(SQLSubModel):
|
||||||
def __init__(self, reach, study):
|
def __init__(self, reach, study):
|
||||||
|
super(Reach, self).__init__(
|
||||||
|
id=-1, status=study.status,
|
||||||
|
owner_scenario=study.status.scenario.id
|
||||||
|
)
|
||||||
|
|
||||||
self._study = study
|
self._study = study
|
||||||
self._reach = reach # Source reach in the study
|
self._reach = reach # Source reach in the study
|
||||||
self._profiles = list(
|
self._profiles = list(
|
||||||
|
|
@ -101,9 +224,31 @@ class Reach(object):
|
||||||
def has_sediment(self):
|
def has_sediment(self):
|
||||||
return any(map(lambda profile: profile.has_sediment(), self._profiles))
|
return any(map(lambda profile: profile.has_sediment(), self._profiles))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute, ext=""):
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
class River(object):
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version, data=None):
|
||||||
|
return cls._update_submodel(execute, version, data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
return cls._db_load(execute, data)
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
for profile in self._profiles:
|
||||||
|
data["profile"] = profile.geometry.pamhyr_id
|
||||||
|
profile._db_save(execute, data)
|
||||||
|
|
||||||
|
|
||||||
|
class River(SQLSubModel):
|
||||||
def __init__(self, study):
|
def __init__(self, study):
|
||||||
|
super(River, self).__init__(
|
||||||
|
id=-1, status=study.status,
|
||||||
|
owner_scenario=study.status.scenario.id
|
||||||
|
)
|
||||||
|
|
||||||
self._study = study
|
self._study = study
|
||||||
|
|
||||||
# Dict with timestamps as key
|
# Dict with timestamps as key
|
||||||
|
|
@ -137,3 +282,20 @@ class River(object):
|
||||||
self._reachs
|
self._reachs
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_create(cls, execute, ext=""):
|
||||||
|
return cls._create_submodel(execute)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_update(cls, execute, version, data=None):
|
||||||
|
return cls._update_submodel(execute, version, data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _db_load(cls, execute, data=None):
|
||||||
|
return cls._db_load(execute, data)
|
||||||
|
|
||||||
|
def _db_save(self, execute, data=None):
|
||||||
|
for reach in self._reachs:
|
||||||
|
data["reach"] = reach.geometry.pamhyr_id
|
||||||
|
reach._db_save(execute, data)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue