Commit ab9ebc64 authored by Pierre-Antoine Rouby's avatar Pierre-Antoine Rouby
Browse files

pamhyr: Add just-in-time database geometry loading.

Showing with 140 additions and 77 deletions
+140 -77
......@@ -85,9 +85,7 @@ class Friction(SQLSubModel):
sec.begin_strickler = bs
sec.end_strickler = es
new[ind] = sec
return new
yield ind, sec
def _sql_save(self, execute, data = None):
ind = data["ind"]
......
......@@ -68,6 +68,26 @@ class FrictionList(PamhyrModelList):
return ok
def _get_frictions_list(self):
# Frictions list generator is type (int, Point) with the first
# element the index of the Point in list
return list(
map(
lambda p: p[1],
sorted(
self._lst,
key = lambda p: p[0]
)
)
)
@property
def lst(self):
if not isinstance(self._lst, list):
self._lst = self._get_frictions_list()
return self._lst
@property
def frictions(self):
return self.lst
......
......@@ -70,8 +70,6 @@ class PointXYZ(Point, SQLSubModel):
@classmethod
def _sql_load(cls, execute, data = None):
points = []
status = data["status"]
profile = data["profile"]
......@@ -81,10 +79,6 @@ class PointXYZ(Point, SQLSubModel):
f"WHERE profile = {profile.id}"
)
# Create points list
for _ in table:
points.append(None)
# Fill points list with new point
for row in table:
ind = row[0]
......@@ -111,9 +105,7 @@ class PointXYZ(Point, SQLSubModel):
)
)
points[ind] = new
return points
yield ind, new
def _sql_save(self, execute, data = None):
profile = data["profile"]
......
......@@ -57,18 +57,34 @@ class Profile(object):
self._profile_type = _type
def __len__(self):
return len(self._points)
return len(self.points)
@property
def number_points(self):
return len(self._points)
return len(self.points)
def _get_points_list(self):
# Points list generator is type (int, Point) with the first
# element the index of the Point in list
return list(
map(
lambda p: p[1],
sorted(
self._points,
key = lambda p: p[0]
)
)
)
@property
def points(self):
return self._points.copy()
if not isinstance(self._points, list):
self._points = self._get_points_list()
return self._points
def point(self, index):
return self._points[index]
return self.points[index]
@property
def reach(self):
......@@ -115,7 +131,7 @@ class Profile(object):
@property
def nb_points(self):
return len(self._points)
return len(self.points)
@property
def kp(self):
......@@ -170,8 +186,8 @@ class Profile(object):
self._status.modified()
def point(self, i:int):
if i < len(self._points):
return self._points[i]
if i < len(self.points):
return self.points[i]
return None
......@@ -181,7 +197,7 @@ class Profile(object):
Returns:
The list of named point
"""
return [point for point in self._points
return [point for point in self.points
if point.point_is_named()]
......@@ -195,7 +211,7 @@ class Profile(object):
Returns:
Nothing.
"""
self._points.insert(index, point)
self.points.insert(index, point)
self._status.modified()
......@@ -218,7 +234,7 @@ class Profile(object):
)
)
self._points = list(
self.points = list(
filter(
lambda p: p not in points,
self.points
......@@ -235,7 +251,7 @@ class Profile(object):
Returns:
Nothing.
"""
self._points = list(
self.points = list(
filter(
lambda p: p not in points,
self.points
......@@ -246,10 +262,10 @@ class Profile(object):
# Move
def move_up_point(self, index: int):
if index < len(self._points):
if index < len(self.points):
next = index - 1
p = self._points
p = self.points
p[index], p[next] = p[next], p[index]
self._status.modified()
......@@ -257,7 +273,7 @@ class Profile(object):
if index >= 0:
prev = index + 1
p = self._points
p = self.points
p[index], p[prev] = p[prev], p[index]
self._status.modified()
......@@ -271,8 +287,8 @@ class Profile(object):
elif column == 'z':
predicate = lambda p: p.z
self._points = sorted(
self._points,
self.points = sorted(
self.points,
key=predicate,
reverse=is_reversed
)
......@@ -280,10 +296,10 @@ class Profile(object):
@timer
def sort_with_indexes(self, indexes: list):
if len(self._points) != len(indexes):
if len(self.points) != len(indexes):
logger.critical("Indexes list do not correspond to point list")
self._points = list(
self.points = list(
map(
lambda x: x[1],
sorted(
......
......@@ -16,6 +16,7 @@
# -*- coding: utf-8 -*-
import logging
import numpy as np
from typing import List
......@@ -27,6 +28,8 @@ from Model.Geometry.Profile import Profile
from Model.Geometry.PointXYZ import PointXYZ
from Model.Geometry.Vector_1d import Vector1d
logger = logging.getLogger()
class ProfileXYZ(Profile, SQLSubModel):
_sub_classes = [
PointXYZ,
......@@ -108,7 +111,7 @@ class ProfileXYZ(Profile, SQLSubModel):
table = execute(
"SELECT id, ind, name, kp, num, code1, code2, sl " +
"FROM geometry_profileXYZ " +
f"WHERE reach = {reach}"
f"WHERE reach = {reach.id}"
)
for _ in table:
......@@ -145,9 +148,11 @@ class ProfileXYZ(Profile, SQLSubModel):
data["profile"] = new
new._points = PointXYZ._sql_load(execute, data)
profiles[ind] = new
yield ind, new
# profiles[ind] = new
return profiles
# return profiles
def _sql_save(self, execute, data = None):
ok = True
......@@ -170,7 +175,7 @@ class ProfileXYZ(Profile, SQLSubModel):
execute(f"DELETE FROM geometry_pointXYZ WHERE profile = {self.id}")
ind = 0
for point in self._points:
for point in self.points:
data["ind"] = ind
ok &= point._sql_save(execute, data)
ind += 1
......@@ -222,16 +227,16 @@ class ProfileXYZ(Profile, SQLSubModel):
def x(self):
return [point.x for point in self._points]
return [point.x for point in self.points]
def y(self):
return [point.y for point in self._points]
return [point.y for point in self.points]
def z(self):
return [point.z for point in self._points]
return [point.z for point in self.points]
def names(self):
return [point.name for point in self._points]
return [point.name for point in self.points]
def x_max(self):
return max(self.filter_isnan(self.x()))
......@@ -262,7 +267,7 @@ class ProfileXYZ(Profile, SQLSubModel):
"""
for point in list_points:
pt = PointXYZ(*point, profile=self, status=self._status)
self._points.append(pt)
self.points.append(pt)
self._status.modified()
def get_point_i(self, index: int) -> PointXYZ:
......@@ -275,7 +280,7 @@ class ProfileXYZ(Profile, SQLSubModel):
The point.
"""
try:
return self._points[index]
return self.points[index]
except IndexError:
raise IndexError(f"Invalid point index: {index}")
......@@ -286,7 +291,7 @@ class ProfileXYZ(Profile, SQLSubModel):
Nothing.
"""
point_xyz = PointXYZ(0., 0., 0., profile=self, status=self._status)
self._points.append(point_xyz)
self.points.append(point_xyz)
self._status.modified()
def insert(self, index: int):
......@@ -299,7 +304,7 @@ class ProfileXYZ(Profile, SQLSubModel):
The new point.
"""
point = PointXYZ(0., 0., 0., profile=self, status=self._status)
self._points.insert(index, point)
self.points.insert(index, point)
self._status.modified()
return point
......@@ -315,9 +320,9 @@ class ProfileXYZ(Profile, SQLSubModel):
return [x for x in lst if not np.isnan(x)]
def _first_point_not_nan(self):
first_point = self._points[0]
first_point = self.points[0]
for point in self._points:
for point in self.points:
if not point.is_nan():
first_point = point
break
......@@ -325,9 +330,9 @@ class ProfileXYZ(Profile, SQLSubModel):
return first_point
def _last_point_not_nan(self):
last_point = self._points[-1]
last_point = self.points[-1]
for point in self._points[::-1]:
for point in self.points[::-1]:
if not point.is_nan():
last_point = point
break
......@@ -354,13 +359,13 @@ class ProfileXYZ(Profile, SQLSubModel):
first_point_not_nan = self._first_point_not_nan()
last_point_not_nan = self._last_point_not_nan()
for index, point in enumerate(self._points):
for index, point in enumerate(self.points):
if point.point_is_named():
index_first_named_point = index
first_named_point = point
break
for point in reversed(self._points):
for point in reversed(self.points):
if point.point_is_named():
last_named_point = point
break
......@@ -378,7 +383,7 @@ class ProfileXYZ(Profile, SQLSubModel):
vector = Vector1d(first_point_not_nan, last_point_not_nan)
normalized_direction_vec = vector.normalized_direction_vector()
for point in self._points:
for point in self.points:
xi = point.x - first_named_point.x
yi = point.y - first_named_point.y
station_i = (normalized_direction_vec[0] * xi +
......@@ -390,7 +395,7 @@ class ProfileXYZ(Profile, SQLSubModel):
vector = Vector1d(first_point_not_nan, last_point_not_nan)
normalized_direction_vec = vector.normalized_direction_vector()
for point in self._points:
for point in self.points:
xi = point.x - first_point_not_nan.x
yi = point.y - first_point_not_nan.y
station_i = (normalized_direction_vec[0] * xi +
......
......@@ -94,8 +94,8 @@ class Reach(SQLSubModel):
Returns:
The profile at index i
"""
if i < len(self._profiles):
return self._profiles[i]
if i < len(self.profiles):
return self.profiles[i]
return None
......@@ -106,12 +106,32 @@ class Reach(SQLSubModel):
return self._parent.name
def _get_profiles_list(self):
# Profiles list generator is type (int, Point) with the first
# element the index of the Point in list
logger.info(f"Load profiles from reach {self.name}")
return list(
map(
lambda p: p[1],
sorted(
self._profiles,
key = lambda p: p[0]
)
)
)
def __len__(self):
if not isinstance(self._profiles, list):
self._profiles = self._get_profiles_list()
return len(self._profiles)
@property
def profiles(self):
return self._profiles.copy()
if not isinstance(self._profiles, list):
self._profiles = self._get_profiles_list()
return self._profiles
def get_profiles_from_kp(self, kp):
return list(
......@@ -126,14 +146,14 @@ class Reach(SQLSubModel):
Returns:
Number of profiles
"""
return len(self._profiles)
return len(self.profiles)
def get_geometry(self) -> List[Profile]:
"""
Returns:
The profiles list.
"""
return self._profiles
return self.profiles
def _update_profile_numbers(self):
"""Update profiles index
......@@ -155,7 +175,7 @@ class Reach(SQLSubModel):
"""
profile = ProfileXYZ(reach=self, status=self._status)
self._profiles.insert(index, profile)
self.profiles.insert(index, profile)
self._update_profile_numbers()
self._status.modified()
......@@ -171,7 +191,7 @@ class Reach(SQLSubModel):
Returns:
Nothing.
"""
self._profiles.insert(index, profile)
self.profiles.insert(index, profile)
self._update_profile_numbers()
self._status.modified()
......@@ -195,7 +215,7 @@ class Reach(SQLSubModel):
)
)
self._profiles = list(
self.profiles = list(
filter(
lambda p: p not in profiles,
self.profiles
......@@ -213,7 +233,7 @@ class Reach(SQLSubModel):
Returns:
Nothing.
"""
self._profiles = list(
self.profiles = list(
filter(
lambda p: p not in profiles,
self.profiles
......@@ -227,7 +247,7 @@ class Reach(SQLSubModel):
if index < len(self.profiles):
next = index - 1
p = self._profiles
p = self.profiles
p[index], p[next] = p[next], p[index]
self._status.modified()
......@@ -235,7 +255,7 @@ class Reach(SQLSubModel):
if index >= 0:
prev = index + 1
p = self._profiles
p = self.profiles
p[index], p[prev] = p[prev], p[index]
self._status.modified()
......@@ -347,7 +367,7 @@ class Reach(SQLSubModel):
Tuple of complete and incomplete guidelines name.
"""
# Get all point contains into a guideline
named_points = [profile.named_points() for profile in self._profiles]
named_points = [profile.named_points() for profile in self.profiles]
points_name = list(
map(
lambda lst: list(map(lambda p: p.name, lst)),
......@@ -422,8 +442,8 @@ class Reach(SQLSubModel):
@timer
def sort(self, is_reversed: bool = False):
self._profiles = sorted(
self._profiles,
self.profiles = sorted(
self.profiles,
key=lambda profile: profile.kp,
reverse=is_reversed
)
......@@ -431,10 +451,10 @@ class Reach(SQLSubModel):
@timer
def sort_with_indexes(self, indexes: list):
if len(self._profiles) != len(indexes):
if len(self.profiles) != len(indexes):
logger.critical("Indexes list do not correspond to profile list")
self._profiles = list(
self.profiles = list(
map(
lambda x: x[1],
sorted(
......@@ -474,7 +494,7 @@ class Reach(SQLSubModel):
**d, reach=self, status=self._status
)
prof.import_points(profile)
self._profiles.append(prof)
self.profiles.append(prof)
self._update_profile_numbers()
self._status.modified()
......@@ -538,8 +558,8 @@ class Reach(SQLSubModel):
# TODO: Move this function to model reach
def export_reach(self, filename):
with open(f"{filename}", "w") as file_st:
for index in range(len(self._profiles)):
profile = self._profiles[index]
for index in range(len(self.profiles)):
profile = self.profiles[index]
for v in profile.header:
file_st.write(f"{v:>6}")
......
......@@ -244,10 +244,8 @@ class InitialConditions(SQLSubModel):
data = data
)
if new._data is None:
return None
return new
if new._data is not None:
yield new
def _sql_save(self, execute, data = None):
ok = True
......
......@@ -16,6 +16,7 @@
# -*- coding: utf-8 -*-
import types
from copy import copy
from tools import trace, timer
......@@ -57,6 +58,19 @@ class InitialConditionsDict(PamhyrModelDict):
return ok
def get(self, key):
if key in self._dict:
v = self._dict[key]
if isinstance(v, types.GeneratorType):
self._dict[key] = list(v)[0]
return self._dict[key]
new = self.new(key)
self.set(key, new)
return new
def new(self, reach):
new = InitialConditions(reach = reach, status = self._status)
self.set(reach, new)
......
......@@ -59,12 +59,12 @@ class PamhyrModelList(SQLSubModel):
# MODEL METHOD #
################
def __len__(self):
return len(self._lst)
@property
def lst(self):
return self._lst.copy()
return self._lst
def __len__(self):
return len(self.lst)
def get(self, row):
return self._lst[row]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment