Compare commits

..

5 Commits

3 changed files with 54 additions and 27 deletions

View File

@ -92,6 +92,7 @@ class ProfileXYZ(Profile, SQLSubModel):
self.station_up_to_date = False
self._get_water_limits_cache = {}
self._get_water_limits_ac_cache = {}
@classmethod
def _db_create(cls, execute, ext=""):
@ -621,6 +622,7 @@ class ProfileXYZ(Profile, SQLSubModel):
"""
return [x for x in lst if not np.isnan(x)]
@timer
def speed(self, q, z):
area = self.wet_area(z)
@ -672,6 +674,7 @@ class ProfileXYZ(Profile, SQLSubModel):
length += line.length
return length
@timer
def compute_wet_area(self, z):
area = 0.0
if len(self.tab.L) > 0:
@ -712,6 +715,7 @@ class ProfileXYZ(Profile, SQLSubModel):
if len(line.coords) > 2:
poly = geometry.Polygon(line)
area += poly.area
return area
def wet_radius(self, z):
@ -734,6 +738,7 @@ class ProfileXYZ(Profile, SQLSubModel):
line = geometry.LineString(list(zip(station, zz)))
return line
@timer
def wet_lines(self, z):
points = self._points
if len(points) < 3:
@ -810,7 +815,6 @@ class ProfileXYZ(Profile, SQLSubModel):
return points
def get_nb_wet_areas(self, z):
n_zones = 0
points = self._points
if points[0].z <= z:
@ -822,10 +826,13 @@ class ProfileXYZ(Profile, SQLSubModel):
return n_zones
@timer
def get_all_water_limits_ac(self, z):
"""
Determine all water limits for z elevation.
"""
if z in self._get_water_limits_ac_cache:
return self._get_water_limits_ac_cache[z]
points = self._points
if len(points) < 3:
@ -858,10 +865,19 @@ class ProfileXYZ(Profile, SQLSubModel):
logger.error(f"ERROR in get_all_water_limits_ac")
return [], []
return start, list(reversed(end))
res = start, list(reversed(end))
self._get_water_limits_ac_cache[z] = res
return res
@timer
def get_water_limits(self, z):
if z in self._get_water_limits_cache:
return self._get_water_limits_cache[z]
return self.get_water_limits_compute(z)
def get_water_limits_compute(self, z):
"""
Determine left and right limits of water elevation.
"""
@ -870,9 +886,6 @@ class ProfileXYZ(Profile, SQLSubModel):
i_left = -1
i_right = -1
if z in self._get_water_limits_cache:
return self._get_water_limits_cache[z]
for i in range(self.number_points):
if self.point(i).z <= z:
i_left = i
@ -919,15 +932,20 @@ class ProfileXYZ(Profile, SQLSubModel):
# Create a generator to improve results data reading speed
yield pt_left, pt_right
@timer
def compute_tabulation(self):
sorted_points = sorted(self._points, key=lambda p: p.z)
self.tab.z = np.array([p.z for p in sorted_points], np.float64)
self.tab.L = np.zeros(len(self.tab.z), np.float64)
self.tab.A = np.zeros(len(self.tab.z), np.float64)
for i in range(1, len(self.tab.z)):
self.tab.L[i] = self.compute_wet_width(self.tab.z[i])
dx = (self.tab.L[i] + self.tab.L[i-1])/2
dz = self.tab.z[i] - self.tab.z[i-1]
self.tab.A[i] = self.tab.A[i-1] + dz * dx
self.tab_up_to_date = True

View File

@ -79,7 +79,8 @@ class Profile(SQLSubModel):
# If is a generator, compute value(s)
if isinstance(v, types.GeneratorType):
v = self._data[timestamp][key] = next(v)
v = next(v)
self._data[timestamp][key] = v
return v

View File

@ -1083,7 +1083,7 @@ class Mage8(Mage):
newline()
reachs = []
iprofiles = {}
iprofiles = []
profile_len = []
reach_offset = {}
@ -1099,14 +1099,14 @@ class Mage8(Mage):
i2 = data[2*i+1] - 1
# Add profile id correspondance to reach
key = (i1, i2)
iprofiles[key] = r
for key in range(i1, i2 + 1):
iprofiles.append(i)
# Profile ID offset
reach_offset[r] = i1
profile_len.append(i2-i1+1)
logger.debug(f"read_bin: iprofiles = {iprofiles}")
logger.debug(f"read_bin: iprofiles = {len(iprofiles)}")
endline()
@ -1124,16 +1124,6 @@ class Mage8(Mage):
# Data
newline()
def ip_to_r(i): return iprofiles[
next(
filter(
lambda k: k[0] <= i <= k[1],
iprofiles
)
)
]
def ip_to_ri(r, i): return i - reach_offset[r]
# check results and geometry consistency
for i, r in enumerate(reachs):
lp = len(r.profiles)
@ -1144,6 +1134,8 @@ class Mage8(Mage):
return
ts = set()
tmp_table = {}
end = False
while not end:
n = read_int(1)[0]
@ -1152,15 +1144,18 @@ class Mage8(Mage):
f, dtype=np.byte, count=1)).decode()
data = read_float(n)
# logger.debug(f"read_bin: timestamp = {timestamp} sec")
if key not in tmp_table:
tmp_table[key] = []
tmp_table[key].append(data)
ts.add(timestamp)
if key in ["Z", "Q"]:
for i, d in enumerate(data):
# Get reach corresponding to profile ID
reach = ip_to_r(i)
reach = reachs[iprofiles[i]]
# Get profile id in reach
ri = ip_to_ri(reach, i)
ri = i - reach_offset[reach]
# Set data for profile RI
reach.set(ri, timestamp, key, d)
@ -1176,6 +1171,10 @@ class Mage8(Mage):
endline()
end = newline().size <= 0
table = {}
for k in tmp_table:
table[k] = np.array(tmp_table[k])
results.set("timestamps", ts)
ts_list = sorted(ts)
logger.info(f"compute tab...")
@ -1185,14 +1184,22 @@ class Mage8(Mage):
logger.info(f"compute velocity...")
for r in reachs:
for t in ts_list:
for i, p in enumerate(r.profiles):
velocity_arr = np.zeros((len(ts), len(iprofiles)))
for ti, t in enumerate(ts_list):
j = 0
for r in reachs:
for pi, p in enumerate(r.profiles):
v = p.geometry.speed(
p.get_ts_key(t, "Q"),
p.get_ts_key(t, "Z")
)
r.set(i, t, "V", v)
r.set(pi, t, "V", v)
velocity_arr[ti, j] = v
j += 1
table["V"] = velocity_arr
results.set("table", table)
logger.info(f"read_bin: ... end with {len(ts)} timestamp read")
results.bufferize("Z")
@ -1322,6 +1329,7 @@ class Mage8(Mage):
newline()
npts = read_int(n)
endline()
sum_npts = sum(npts)
logger.debug(f"read_gra: Number of points: {sum_npts}")