Compare commits

..

No commits in common. "e8f1f0ac43fe3c510a11aa51ab208f7339446289" and "a61d130baa12a1041d15b4634e1645e3108b316e" have entirely different histories.

5 changed files with 43 additions and 287 deletions

View File

@ -875,9 +875,7 @@ class ProfileXYZ(Profile, SQLSubModel):
if z in self._get_water_limits_cache: if z in self._get_water_limits_cache:
return self._get_water_limits_cache[z] return self._get_water_limits_cache[z]
v = self.get_water_limits_compute(z) return self.get_water_limits_compute(z)
return v
def get_water_limits_compute(self, z): def get_water_limits_compute(self, z):
""" """
@ -885,59 +883,54 @@ class ProfileXYZ(Profile, SQLSubModel):
""" """
# Get the index of first point with elevation lesser than water # Get the index of first point with elevation lesser than water
# elevation (for the right and left river side) # elevation (for the right and left river side)
i_left = next( i_left = -1
filter( i_right = -1
lambda i: self.point(i).z <= z,
range(self.number_points)
),
-1
)
i_right = next( for i in range(self.number_points):
filter( if self.point(i).z <= z:
lambda i: self.point(i).z <= z, i_left = i
reversed(range(self.number_points)) break
),
-1 for i in reversed(range(self.number_points)):
) if self.point(i).z <= z:
i_right = i
break
# Interpolate points at river left side # Interpolate points at river left side
if (i_left > 0): if (i_left > 0):
pi = self.point(i_left) if abs(self.point(i_left - 1).z - self.point(i_left).z) < 1e-20:
pim1 = self.point(i_left - 1) pt_left = self.point(i_left)
if abs(pim1.z - pi.z) < 1e-20:
pt_left = pi
else: else:
fact = (z - pi.z) / (pim1.z - pi.z) fact = (z - self.point(i_left).z) / \
x = pi.x + fact * (pim1.x - pi.x) (self.point(i_left - 1).z - self.point(i_left).z)
y = pi.y + fact * (pim1.y - pi.y) x = self.point(i_left).x + fact * \
(self.point(i_left - 1).x - self.point(i_left).x)
y = self.point(i_left).y + fact * \
(self.point(i_left - 1).y - self.point(i_left).y)
pt_left = PointXYZ(x=x, y=y, z=z, name="wl_left") pt_left = PointXYZ(x=x, y=y, z=z, name="wl_left")
else: else:
pt_left = self.point(0) pt_left = self.point(0)
# Interpolate points at river right side # Interpolate points at river right side
if (i_right < self.number_points - 1): if (i_right < self.number_points - 1):
pi = self.point(i_right) if abs(self.point(i_right + 1).z - self.point(i_right).z) < 1e-20:
pip1 = self.point(i_right + 1) pt_right = self.point(i_right)
if abs(pip1.z - pi.z) < 1e-20:
pt_right = pi
else: else:
fact = (z - pi.z) / (pip1.z - pi.z) fact = (z - self.point(i_right).z) / \
x = pi.x + fact * (pip1.x - pi.x) (self.point(i_right + 1).z - self.point(i_right).z)
y = pi.y + fact * (pip1.y - pi.y) x = self.point(i_right).x + fact * \
(self.point(i_right + 1).x - self.point(i_right).x)
y = self.point(i_right).y + fact * \
(self.point(i_right + 1).y - self.point(i_right).y)
pt_right = PointXYZ(x=x, y=y, z=z, name="wl_right") pt_right = PointXYZ(x=x, y=y, z=z, name="wl_right")
else: else:
pt_right = self.point(self.number_points - 1) pt_right = self.point(self.number_points - 1)
v = (pt_left, pt_right)
# Put results in cache # Put results in cache
self._get_water_limits_cache[z] = v self._get_water_limits_cache[z] = (pt_left, pt_right)
# Create a generator to improve results data reading speed # Create a generator to improve results data reading speed
yield v yield pt_left, pt_right
@timer @timer
def compute_tabulation(self): def compute_tabulation(self):

View File

@ -157,185 +157,8 @@ class AdditionalData(SQLSubModel):
return True return True
class TableData(SQLSubModel):
_sub_classes = []
def __init__(self, id=-1, study=None,
legend="", data=None,
owner_scenario=-1):
super(TableData, self).__init__(
id=id, status=study.status,
owner_scenario=owner_scenario
)
self._study = study
self._legend = legend
self._data = data
@property
def data(self):
return self._data
@classmethod
def _db_create(cls, execute, ext=""):
execute(f"""
CREATE TABLE results_table_data{ext} (
{cls.create_db_add_pamhyr_id()},
result INTEGER NOT NULL,
legend TEXT NOT NULL,
unit TEXT NOT NULL,
data_shape_x INTEGER NOT NULL,
data_shape_y INTEGER NOT NULL,
data_shape_z INTEGER DEFAULT -1,
data BLOB NOT NULL,
{Scenario.create_db_add_scenario()},
{Scenario.create_db_add_scenario_fk()},
FOREIGN KEY(result) REFERENCES results(pamhyr_id),
PRIMARY KEY(pamhyr_id, result, legend, scenario)
)
""")
if ext != "":
return True
return cls._create_submodel(execute)
@classmethod
def _db_update(cls, execute, version, data=None):
major, minor, release = version.strip().split(".")
create = False
if major == "0" and int(minor) == 2:
if int(release) < 7 and not create:
cls._db_create(execute)
create = True
return cls._update_submodel(execute, version, data)
@classmethod
def _db_load(cls, execute, data=None):
res = {}
study = data['study']
status = data['status']
scenario = data["scenario"]
result = data["result"]
rid = data["result_pid"]
table = execute(
"SELECT pamhyr_id, " +
"legend, unit, " +
"data_shape_x, data_shape_y, data_shape_z, " +
"data, " +
"scenario " +
"FROM results_table_data " +
f"WHERE scenario = {scenario.id} " +
f"AND result = {rid}"
)
for v in table:
it = iter(v)
pid = next(it)
legend = next(it)
unit = next(it)
data_shape_x = next(it)
data_shape_y = next(it)
data_shape_z = next(it)
data = next(it)
owner_scenario = next(it)
dtype = cls._unit_to_dtype(unit)
np_data = np.frombuffer(data, dtype=dtype)
if data_shape_y == -1:
np_data = np.reshape(np_data, data_shape_x)
elif data_shape_z == -1:
np_data = np.reshape(np_data, (data_shape_x,
data_shape_y))
else:
np_data = np.reshape(np_data, (data_shape_x,
data_shape_y,
data_shape_z))
new_table = cls(study=study,
legend=legend, data=np_data,
owner_scenario=owner_scenario)
res[legend] = new_table
return res
def _db_save(self, execute, data=None):
if self._status.scenario.id != self._owner_scenario:
return
shape_x = -1
shape_y = -1
shape_z = -1
shape = self._data.shape
if len(shape) == 2:
shape_x, shape_y = shape
elif len(shape == 1):
shape_x, = shape
elif len(shape == 3):
shape_x, shape_y, shape_z = shape
else:
logger.error(
f"Failed to parse numpy shape: {shape}"
)
execute(
"INSERT INTO " +
"results_table_data (pamhyr_id, result, " +
"legend, unit, " +
"data_shape_x, data_shape_y, data_shape_z, " +
"data, " +
"scenario) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
self._pamhyr_id, data["result"],
self._legend, self._dtype_to_unit(self._data.dtype),
shape_x, shape_y, shape_z,
self._data,
self._owner_scenario
)
return True
@classmethod
def _unit_to_dtype(cls, unit):
t = {
"i32": np.int32, "i64": np.int64,
"u32": np.uint32, "u64": np.uint64,
"f32": np.float32, "f64": np.float64,
}
return t[unit]
def _dtype_to_unit(self, dtype):
t = {
np.dtype(np.int32): "i32", np.dtype(np.int64): "i64",
np.dtype(np.uint32): "u32", np.dtype(np.uint64): "u64",
np.dtype(np.float32): "f32", np.dtype(np.float64): "f64",
}
return t[dtype]
def table(self):
return self._data
def __len__(self):
return len(self._data)
def __getitem__(self, key):
if isinstance(key, tuple):
return self._data[key[0], key[1]]
self._date[key]
class Results(SQLSubModel): class Results(SQLSubModel):
_sub_classes = [River, TableData, AdditionalData] _sub_classes = [River, AdditionalData]
def __init__(self, id=-1, study=None, solver=None, def __init__(self, id=-1, study=None, solver=None,
repertory="", name="0"): repertory="", name="0"):
@ -356,11 +179,8 @@ class Results(SQLSubModel):
"creation_date": datetime.now(), "creation_date": datetime.now(),
"study_revision": study.status.version, "study_revision": study.status.version,
"additional_data": [], "additional_data": [],
"table": {},
} }
self._ts_index = {}
if solver is not None: if solver is not None:
self.set("solver_type", solver._type) self.set("solver_type", solver._type)
@ -401,10 +221,6 @@ class Results(SQLSubModel):
def get_timestamp_id(self, ts): def get_timestamp_id(self, ts):
return self._ts_index[ts] return self._ts_index[ts]
def compute_timestamp_index(self):
for i, ts in enumerate(self._meta_data["timestamps"]):
self._ts_index[ts] = i
def reload(self): def reload(self):
return self._solver.results( return self._solver.results(
self._study, self._study,
@ -502,19 +318,11 @@ class Results(SQLSubModel):
new_results.set("study_revision", revision) new_results.set("study_revision", revision)
new_results.set("creation_date", creation_date) new_results.set("creation_date", creation_date)
data["result_pid"] = pid
data["result"] = new_results
table_data = TableData._db_load(execute, data)
new_results.set("table", table_data)
sf = ">" + ''.join(itertools.repeat("d", nb_timestamps)) sf = ">" + ''.join(itertools.repeat("d", nb_timestamps))
ts = struct.unpack(sf, timestamps_bytes) ts = struct.unpack(sf, timestamps_bytes)
new_results.set("timestamps", ts) new_results.set("timestamps", ts)
data["timestamps"] = sorted(ts) data["timestamps"] = sorted(ts)
new_results.compute_timestamp_index()
data["parent"] = new_results data["parent"] = new_results
new_results._river = River._db_load(execute, data) new_results._river = River._db_load(execute, data)
@ -523,20 +331,6 @@ class Results(SQLSubModel):
AdditionalData._db_load(execute, data) AdditionalData._db_load(execute, data)
) )
# Update global index
i = 0
for reach in new_results._river.reachs:
nb = len(reach.profiles)
reach.set_global_index(range(i, i + nb + 1))
i += nb
if "Z" in table_data:
for ts in data["timestamps"]:
new_results._river.update_water_limits(
ts,
table_data["Z"][new_results.get_timestamp_id(ts), :]
)
yield (solver_type, new_results) yield (solver_type, new_results)
def _db_save_clear(self, execute, solver_type, data=None): def _db_save_clear(self, execute, solver_type, data=None):
@ -559,11 +353,6 @@ class Results(SQLSubModel):
f"WHERE scenario = {self._owner_scenario} " + f"WHERE scenario = {self._owner_scenario} " +
f"AND result = {pid}" f"AND result = {pid}"
) )
execute(
"DELETE FROM results_table_data " +
f"WHERE scenario = {self._owner_scenario} " +
f"AND result = {pid}"
)
execute( execute(
"DELETE FROM results_add_data " + "DELETE FROM results_add_data " +
f"WHERE scenario = {self._owner_scenario} " + f"WHERE scenario = {self._owner_scenario} " +
@ -607,19 +396,7 @@ class Results(SQLSubModel):
data["result"] = self._pamhyr_id data["result"] = self._pamhyr_id
self._river._db_save(execute, data) self._river._db_save(execute, data)
tables = self.get("table")
for legend in tables:
tables[legend]._db_save(execute, data)
for add_data in self.get("additional_data"): for add_data in self.get("additional_data"):
add_data._db_save(execute, data) add_data._db_save(execute, data)
return True return True
def new_table_data(self, legend, data):
return TableData(
study=self._study,
legend=legend,
data=data,
owner_scenario=self._owner_scenario
)

View File

@ -137,6 +137,7 @@ class Profile(SQLSubModel):
@classmethod @classmethod
def _db_load(cls, execute, data=None): def _db_load(cls, execute, data=None):
new = {}
status = data['status'] status = data['status']
parent = data['parent'] parent = data['parent']
@ -147,8 +148,6 @@ class Profile(SQLSubModel):
loaded = data['loaded_pid'] loaded = data['loaded_pid']
timestamps = data['timestamps'] timestamps = data['timestamps']
new = cls(profile, study, parent)
values = execute( values = execute(
"SELECT pamhyr_id, result, key, " + "SELECT pamhyr_id, result, key, " +
"len_data, data, scenario " + "len_data, data, scenario " +
@ -168,6 +167,12 @@ class Profile(SQLSubModel):
data = next(it) data = next(it)
owner_scenario = next(it) owner_scenario = next(it)
if profile not in new:
new_data = cls(profile, study, parent)
new[profile] = new_data
else:
new_data = new[profile]
if key in ["Z", "Q", "V"]: if key in ["Z", "Q", "V"]:
sf = ">" + ''.join(itertools.repeat("f", len_data)) sf = ">" + ''.join(itertools.repeat("f", len_data))
len_values = len(values) len_values = len(values)
@ -180,11 +185,11 @@ class Profile(SQLSubModel):
) )
for timestamp, value in zip(timestamps, values): for timestamp, value in zip(timestamps, values):
new.set(timestamp, key, value) new_data.set(timestamp, key, value)
if key == "Z": if key == "Z":
new.update_water_limits(timestamp, value) new_data.update_water_limits(timestamp, value)
return new return list(new.values())
@classmethod @classmethod
def _db_load_data_sl_format(cls, values, len_data, timestamps): def _db_load_data_sl_format(cls, values, len_data, timestamps):
@ -356,10 +361,6 @@ class Reach(SQLSubModel):
for i, p in enumerate(self._profiles): for i, p in enumerate(self._profiles):
self._buffers[key][:, i] = p.get_key(key) self._buffers[key][:, i] = p.get_key(key)
def update_water_limits(self, timestamp, z_data):
for profile, z in zip(self._profiles, z_data):
profile.update_water_limits(timestamp, z)
@classmethod @classmethod
def _db_create(cls, execute, ext=""): def _db_create(cls, execute, ext=""):
return cls._create_submodel(execute) return cls._create_submodel(execute)
@ -379,7 +380,7 @@ class Reach(SQLSubModel):
for i, profile in enumerate(reach.profiles): for i, profile in enumerate(reach.profiles):
data["profile"] = profile data["profile"] = profile
new_reach._profiles += [Profile._db_load(execute, data)] new_reach._profiles += Profile._db_load(execute, data)
return new_reach return new_reach
@ -434,15 +435,6 @@ class River(SQLSubModel):
) )
) )
def update_water_limits(self, timestamp, data):
for reach in self._reachs:
ind = reach.global_index
reach.update_water_limits(
timestamp,
data[ind[0]:ind[1]]
)
@classmethod @classmethod
def _db_create(cls, execute, ext=""): def _db_create(cls, execute, ext=""):
return cls._create_submodel(execute) return cls._create_submodel(execute)

View File

@ -46,7 +46,7 @@ logger = logging.getLogger()
class Study(SQLModel): class Study(SQLModel):
_version = "0.2.7" _version = "0.2.6"
_sub_classes = [ _sub_classes = [
Scenario, Scenario,

View File

@ -1206,12 +1206,6 @@ class Mage8(Mage):
j += 1 j += 1
table["V"] = velocity_arr table["V"] = velocity_arr
for legend in table:
table[legend] = results.new_table_data(
legend, table[legend]
)
results.set("table", table) results.set("table", table)
logger.info(f"read_bin: ... end with {len(ts)} timestamp read") logger.info(f"read_bin: ... end with {len(ts)} timestamp read")