diff --git a/Controller/LoadMeasurements.py b/Controller/LoadMeasurements.py index 8d0fad9164f6c35a90e401130b25e0dd0725bf6f..a4fadda7a4b5f89e5733451bd2fd814a2ee5b50e 100644 --- a/Controller/LoadMeasurements.py +++ b/Controller/LoadMeasurements.py @@ -28,6 +28,8 @@ from qrevint.Classes.Uncertainty import Uncertainty import time import os import pickle +from qrevint.MiscLibs.common_functions import cart2pol, pol2cart +from qrevint.Classes.QComp import QComp class LoadMeasurements(QThread): @@ -247,7 +249,7 @@ class LoadMeasurements(QThread): # Load measurement data meas = Measurement(in_file=path_meas, source=type_meas, proc_type='QRev', checked=True, run_oursin=False, use_weighted=self.settings['use_weighted'], - run_map=True) + run_map=False) # Remove invalid transect if self.settings['threshold'] is not None: @@ -440,6 +442,159 @@ class LoadMeasurements(QThread): return meas, change + @staticmethod + def compute_topbot_speed(transect): + """Compute top and bottom extrapolated speed. + + Parameters + ---------- + transect: TransectData + """ + + delta_t = np.tile(1.0, transect.w_vel.u_processed_mps.shape[1]) + + # Compute extrapolated cell size and depth + n_ensembles = transect.w_vel.u_processed_mps.shape[1] + depth_selected = getattr(transect.depths, transect.depths.selected) + top_cell_size = np.repeat(np.nan, n_ensembles) + top_cell_depth = np.repeat(np.nan, n_ensembles) + bottom_cell_size = np.repeat(np.nan, n_ensembles) + bottom_cell_depth = np.repeat(np.nan, n_ensembles) + for n in range(n_ensembles): + # Identify topmost 1 and 3 valid cells + idx_temp = np.where( + np.logical_not(np.isnan(transect.w_vel.u_processed_mps[:, n])) + )[0] + if len(idx_temp) > 0: + # Compute top + top_cell_size[n] = ( + depth_selected.depth_cell_depth_m[idx_temp[0], n] + - 0.5 * depth_selected.depth_cell_size_m[idx_temp[0], n] + ) + top_cell_depth[n] = top_cell_size[n] / 2 + # Compute bottom + bottom_cell_size[n] = depth_selected.depth_processed_m[n] - ( + depth_selected.depth_cell_depth_m[idx_temp[-1], n] + + 0.5 * depth_selected.depth_cell_size_m[idx_temp[-1], n] + ) + bottom_cell_depth[n] = ( + depth_selected.depth_processed_m[n] - 0.5 * bottom_cell_size[n] + ) + else: + top_cell_size[n] = 0 + top_cell_depth[n] = 0 + bottom_cell_size[n] = 0 + bottom_cell_depth[n] = 0 + # Compute top speed + u_top = ( + QComp.compute_top_component( + transect=transect, + component=transect.w_vel.u_processed_mps, + delta_t=delta_t, + ) + / top_cell_size + ) + v_top = ( + QComp.compute_top_component( + transect=transect, + component=transect.w_vel.v_processed_mps, + delta_t=delta_t, + ) + / top_cell_size + ) + + # Compute bottom speed + u_bot = ( + QComp.compute_bottom_component( + transect=transect, + component=transect.w_vel.u_processed_mps, + delta_t=delta_t, + ) + / bottom_cell_size + ) + v_bot = ( + QComp.compute_bottom_component( + transect=transect, + component=transect.w_vel.v_processed_mps, + delta_t=delta_t, + ) + / bottom_cell_size + ) + return u_top, v_top, u_bot, v_bot + + @staticmethod + def add_extrapolated_topbot(transect, discharge, water_speed, primary_velocity): + # Compute extrapolated cell size and depth + n_ensembles = water_speed.shape[1] + depth_selected = getattr(transect.depths, transect.depths.selected) + top_cell_size = np.repeat(np.nan, n_ensembles) + top_cell_depth = np.repeat(np.nan, n_ensembles) + bottom_cell_size = np.repeat(np.nan, n_ensembles) + bottom_cell_depth = np.repeat(np.nan, n_ensembles) + for n in range(n_ensembles): + # Identify topmost valid cells + idx_temp = np.where(np.logical_not(np.isnan(water_speed[:, n])))[0] + if len(idx_temp) > 0: + # Compute top + top_cell_size[n] = ( + depth_selected.depth_cell_depth_m[idx_temp[0], n] + - 0.5 * depth_selected.depth_cell_size_m[idx_temp[0], n] + ) + top_cell_depth[n] = top_cell_size[n] / 2 + # Compute bottom + bottom_cell_size[n] = depth_selected.depth_processed_m[n] - ( + depth_selected.depth_cell_depth_m[idx_temp[-1], n] + + 0.5 * depth_selected.depth_cell_size_m[idx_temp[-1], n] + ) + bottom_cell_depth[n] = ( + depth_selected.depth_processed_m[n] - 0.5 * bottom_cell_size[n] + ) + else: + top_cell_size[n] = 0 + top_cell_depth[n] = 0 + bottom_cell_size[n] = 0 + bottom_cell_depth[n] = 0 + + # Expanded arrays to include extrapolated cell size and depth + expanded_cell_size = np.vstack( + [top_cell_size, depth_selected.depth_cell_size_m, bottom_cell_size] + ) + expanded_cell_depth = np.vstack( + [top_cell_depth, depth_selected.depth_cell_depth_m, bottom_cell_depth] + ) + + # Expand array to include extrapolated top and bottom speeds + expanded_water_speed = np.vstack( + [discharge.top_speed, primary_velocity, discharge.bottom_speed] + ) + + # Fix expanded_water_speed for excluded depth cells + for n in range(expanded_water_speed.shape[1]): + idx = np.where(transect.w_vel.valid_data[6, :, n]) + if len(idx[0]) > 0 and idx[0][0] > 0: + for row in range(idx[0][0]): + expanded_water_speed[row + 1, n] = expanded_water_speed[row, n] + + return expanded_cell_size, expanded_cell_depth, expanded_water_speed + + @staticmethod + def compute_x_axis(transect): + """Compute x axis data.""" + + # x axis is length + boat_track = transect.boat_vel.compute_boat_track( + transect=transect + ) + x = boat_track["distance_m"] + x = x[transect.in_transect_idx] + + # Shift data to account for edge distance + if transect.start_edge == "Right": + x = np.abs(x - max(x)) + + x = x + transect.edges.left.distance_m + return x + @staticmethod def create_df(measurements_dict): """ Create a pandas DataFrame from the measurement dictionary @@ -504,22 +659,90 @@ class LoadMeasurements(QThread): navref_status = getattr(meas.qa, current_settings['NavRef'])["status"] water_status = meas.qa.w_vel["status"] - streamwise_velocity = meas.map.streamwise_velocity + # if meas.map is not None: + # primary_velocity = meas.map.primary_velocity + # # Max velocity + # max_idx = nanargmax(primary_velocity) + # max_value = primary_velocity[max_idx] + # max_depth = meas.map.depth_cells_center[max_idx] + # max_distance = meas.map.distance_cells_center[max_idx] + # max_vertical_depth = meas.map.depths[max_idx[1]] + # + # # Top max velocity + # top_max_idx = nanargmax(primary_velocity[0])[0] + # top_max_value = primary_velocity[0, top_max_idx] + # top_max_depth = meas.map.depth_cells_center[0, top_max_idx] + # top_max_distance = meas.map.distance_cells_center[0, top_max_idx] + # top_max_vertical_depth = meas.map.depths[top_max_idx] + # + # is_top_max_vel = max_idx == (0, top_max_idx) + # else: + transects_max_vel = [] + cell_size_list = [] + cell_depth_list = [] + primary_list = [] + for transect_id in meas.checked_transect_idx: + transect = meas.transects[transect_id] + discharge = meas.discharge[transect_id] + x_velocity = transect.w_vel.u_processed_mps[:, transect.in_transect_idx] + y_velocity = transect.w_vel.v_processed_mps[:, transect.in_transect_idx] + water_speed = (x_velocity ** 2 + y_velocity ** 2) ** 0.5 + + # Compute mean velocity components in each ensemble + w_vel_mean_x = np.nanmean(x_velocity, axis=0) + w_vel_mean_y = np.nanmean(y_velocity, axis=0) + + # Compute a unit vector + direction_ens, _ = cart2pol(w_vel_mean_x, w_vel_mean_y) + unit_vec_x, unit_vec_y = pol2cart(direction_ens, 1) + + # Add top bottom extrapolated velocities + u_top, v_top, u_bot, v_bot = LoadMeasurements.compute_topbot_speed(transect) + x_velocity_all = np.vstack([u_top, x_velocity, u_bot]) + y_velocity_all = np.vstack([v_top, y_velocity, v_bot]) + + # Compute the velocity magnitude in the direction of the mean velocity of each + # ensemble using the dot product and unit vector + primary_velocity = x_velocity_all * unit_vec_x + y_velocity_all * unit_vec_y + + ( + expanded_cell_size, + expanded_cell_depth, + expanded_water_speed, + ) = LoadMeasurements.add_extrapolated_topbot(transect, discharge, water_speed, + primary_velocity) + + max_idx = nanargmax(primary_velocity) + max_value = primary_velocity[max_idx] + transects_max_vel.append(max_value) + cell_size_list.append(expanded_cell_size) + cell_depth_list.append(expanded_cell_depth) + primary_list.append(primary_velocity) + + median_value = np.median(transects_max_vel) + idx_max = transects_max_vel.index(min(transects_max_vel, key=lambda x: abs(x - median_value))) + transect = meas.transects[meas.checked_transect_idx[idx_max]] + cell_depth = cell_depth_list[idx_max] + primary_velocity = primary_list[idx_max] + x = LoadMeasurements.compute_x_axis(transect) + + depth_selected = getattr(transect.depths, transect.depths.selected) + depth_transect = depth_selected.depth_processed_m + # Max velocity - max_idx = nanargmax(streamwise_velocity) - max_value = streamwise_velocity[max_idx] - max_depth = meas.map.depth_cells_center[max_idx] - max_distance = meas.map.distance_cells_center[max_idx] - max_vertical_depth = meas.map.depths[max_idx[1]] + max_idx = nanargmax(primary_velocity) + is_top_max_vel = (max_idx[0] == 0) + max_value = primary_velocity[max_idx] + max_depth = cell_depth[max_idx] + max_distance = x[max_idx[1]] + max_vertical_depth = depth_transect[max_idx[1]] # Top max velocity - top_max_idx = nanargmax(streamwise_velocity[0])[0] - top_max_value = streamwise_velocity[0, top_max_idx] - top_max_depth = meas.map.depth_cells_center[0, top_max_idx] - top_max_distance = meas.map.distance_cells_center[0, top_max_idx] - top_max_vertical_depth = meas.map.depths[top_max_idx] - - same_max = max_idx == (0, top_max_idx) + top_max_idx = nanargmax(primary_velocity[0])[0] + top_max_value = primary_velocity[0, top_max_idx] + top_max_depth = cell_depth[0, top_max_idx] + top_max_distance = x[top_max_idx] + top_max_vertical_depth = depth_transect[top_max_idx] # Loop over transects for id_transect in meas.checked_transect_idx: @@ -547,7 +770,7 @@ class LoadMeasurements(QThread): 'meas_model': str(transect.adcp.model), 'meas_serial': str(transect.adcp.serial_num), 'meas_navigation': nav_ref, - 'is_top_max_vel': str(same_max), + 'is_top_max_vel': str(is_top_max_vel), 'map_max_vel': max_value, 'map_max_vel_depth': max_depth, 'map_max_vel_distance': max_distance, diff --git a/UI/main.py b/UI/main.py index 45c6d0ec6f9d2b10ac3981dfe3223e496be96d14..dedfe02256521418ba8e66d7b4526a88a4e2399a 100644 --- a/UI/main.py +++ b/UI/main.py @@ -303,7 +303,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow): self.showMaximized() self.tableResume.resizeColumnToContents(0) - self.QRame_version = 'QRame v1.26.1 [beta]' + self.QRame_version = 'QRame v1.26.2 [beta]' self.setWindowTitle(self.QRame_version) self.setWindowIcon(QtGui.QIcon(resource_path('QRame.ico')))