def plot_y_lever_arm_error(self, subplot: plt.subplot = None, add_regression: bool = True): """ Plot to find the y lever arm error, which is determined by looking at the correlation between filtered depth and roll. Y lever arm error affects the induced heave by the following equation: Induced Heave Error = -(x_error) * sin(pitch) + (y_error) * sin(roll) * cos(pitch) + (z_error) * (1 - cos(roll) * cos(pitch)) or in isloating the y Induced Heave Error (y) = y_error * sin(roll) * cos(pitch) Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.roll_at_ping_time, self.hpf_depth) subplot.set_ylim(-self.hpf_depth.max() * 4, self.hpf_depth.max() * 4) subplot.set_title('Y Sonar Offset Error') subplot.set_xlabel('Roll (deg)') subplot.set_ylabel('Highpassfilter Depth (m)') if add_regression: self._add_regression_line(subplot, self.roll_at_ping_time, self.hpf_depth)
def plot_attitude_scaling_two(self, subplot: plt.subplot = None, add_regression: bool = True): """ See attitude_scaling_one, same concept. We have two plots for a good reason. If you are trying to differentiate between 1. and 2., do the following: | - if scaling_one and scaling_two have your artifact, its probably a scaling issue | - otherwise, if the plots are different, it most likely is the sound speed one. Inner swath and outer swath | will differ as the swath is curved Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.roll_at_ping_time, self.hpf_inner_slope) subplot.set_ylim(-self.hpf_inner_slope.max() * 4, self.hpf_inner_slope.max() * 4) subplot.set_title('Attitude Scaling/Surface Sound Speed 2') subplot.set_xlabel('Roll (deg)') subplot.set_ylabel('Trimmed Slope (deg)') if add_regression: self._add_regression_line(subplot, self.roll_at_ping_time, self.hpf_inner_slope)
def _add_regression_line(self, ax: plt.subplot, x: np.array, y: np.array): """ Build linear regression of x y data and plot on included ax Parameters ---------- ax pyplot AxesSubplot instance x numpy array, 1d y numpy array, 1d Returns ------- str regression line slope rounded to 6 places as string """ # nan not allowed for regression line filter_nan = np.logical_or(np.isnan(x), np.isnan(y)) x = x[~filter_nan] y = y[~filter_nan] slopes, intercepts, stderrs, percent_deviation = linear_regression(x, y) slope_label = np.round(slopes, 6) ax.plot(x, slopes * x + intercepts, label='y = {}x + {}'.format(slope_label, np.round(intercepts, 6)), color='red') ax.legend() return slope_label
def plot_attitude_scaling_one(self, subplot: plt.subplot = None, add_regression: bool = True): """ | This plot (as well as the trimmed plot scaling_two) deal with identifying: | 1. sensor scaling issues (should not be present in modern systems I think) | 2. rolling with imperfect sound speed (probably more likely) Focusing on the second one: When the soundspeed at the face is incorrect, roll angles will introduce steering angle error, so your beampointingangle will be off. As the roll changes, the error will change, making this a dynamic error that is correlated with roll. We aren't going to make up some kind of time series bpa corrector for this error, so if you have this, i believe you are just screwed. Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.roll_at_ping_time, self.hpf_slope) subplot.set_ylim(-self.hpf_slope.max() * 4, self.hpf_slope.max() * 4) subplot.set_title('Attitude Scaling/Surface Sound Speed 1') subplot.set_xlabel('Roll (deg)') subplot.set_ylabel('Ping Slope (deg)') if add_regression: self._add_regression_line(subplot, self.roll_at_ping_time, self.hpf_slope)
def plot_heave_sound_speed_two(self, subplot: plt.subplot = None, add_regression: bool = True): """ See plot_heave_sound_speed_one. There are two plots for the port/starboard swaths. You need two as the swath artifact is a smile/frown, so the two plots should be mirror images if the artifact exists. A full swath analysis would not show this. Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.vert_motion_at_ping_time, self.hpf_stbd_slope) subplot.set_ylim(-self.hpf_stbd_slope.max() * 4, self.hpf_stbd_slope.max() * 4) subplot.set_title('Heave Through Sound Speed Layers 2') subplot.set_xlabel('Heave (m)') subplot.set_ylabel('Stbd Slope (deg)') if add_regression: self._add_regression_line(subplot, self.vert_motion_at_ping_time, self.hpf_stbd_slope)
def plot_heave_sound_speed_one(self, subplot: plt.subplot = None, add_regression: bool = True): """ Plot to find error associated with heaving through sound speed layers. For flat face sonar that are mostly level while receiving, this affect should be minimal. If I'm understanding this correctly, it's because the system is actively steering the beams using the surface sv sensor. For barrel arrays, there is no active beam steering so there will be an error in the beam angles. Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.vert_motion_at_ping_time, self.hpf_port_slope) subplot.set_ylim(-self.hpf_port_slope.max() * 4, self.hpf_port_slope.max() * 4) subplot.set_title('Heave Through Sound Speed Layers 1') subplot.set_xlabel('Heave (m)') subplot.set_ylabel('Port Slope (deg)') if add_regression: self._add_regression_line(subplot, self.vert_motion_at_ping_time, self.hpf_port_slope)
def plot_yaw_alignment(self, subplot: plt.subplot = None, add_regression: bool = True): """ Plot to determine the misalignment between roll/pitch and heading. For us, the POSMV is a tightly coupled system that provides these three data streams, so there really shouldn't be any yaw misalignment with roll/pitch. Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.pitch_at_ping_time, self.hpf_slope) subplot.set_ylim(-self.hpf_slope.max() * 4, self.hpf_slope.max() * 4) subplot.set_title('Yaw Alignment with Reference') subplot.set_xlabel('Pitch (deg)') subplot.set_ylabel('Ping Slope (deg)') if add_regression: self._add_regression_line(subplot, self.pitch_at_ping_time, self.hpf_slope)
def setup_subplots(subplot: plt.subplot, width: int, height: int, color: str, title: str): """ Configure subplots. :param subplot: plt.subplot :param width: int :param height: int :param color: str :param title: str """ subplot.set_xlim(0, width) subplot.xaxis.tick_top() subplot.set_ylim(height, 0) subplot.grid(color=color, linestyle='-', linewidth=1) subplot.set_aspect('equal', adjustable='box') subplot.set_title(title)
def plot_attitude_latency(self, subplot: plt.subplot = None, add_regression: bool = True): """ Plot to determine the attitude latency either in the POSMV initial processing or the transmission to the sonar. We use roll just because it is the most sensitive, most easy to notice. It's a linear tilt we are looking for, so the timing latency would be equal to the slope of the regression of roll rate vs ping slope. If you add_regression, you can get the slope that equates to the latency adjustment slope of regression = ping slope (deg) / roll rate (deg/s) = latency (s) Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance add_regression bool, if True, will include a regression line """ if subplot is None: subplot = plt.subplots(1)[1] subplot.scatter(self.rollrate_at_ping_time, self.hpf_slope) maxslope = self.hpf_slope.max() subplot.set_ylim(-maxslope * 4, maxslope * 4) subplot.set_title('Attitude Time Latency') subplot.set_xlabel('Roll Rate (deg/s)') subplot.set_ylabel('Ping Slope (deg)') if add_regression: slope = self._add_regression_line(subplot, self.rollrate_at_ping_time, self.hpf_slope) subplot.text(0, maxslope * 3.5, 'calculated latency = {} seconds'.format(slope))
def plot_allowable_percent_deviation(self, subplot: plt.subplot = None): """ Plot the correlation plot between ping time and percent deviation in the ping slope linear regression. Percent deviation here is related to the standard error of the y in the regression. Include bounds for invalid data in the plot as a filled in red area. According to source paper, greater than 5% should be rejected. Need to include segment identification in final version for exluding greater than 5% Parameters ---------- subplot pyplot AxesSubplot instance to add to, if None will generate new instance """ if subplot is None: subplot = plt.subplots(1)[1] subplot.plot(self.times, self.slope_percent_deviation) subplot.set_ylim(self.slope_percent_deviation.min(), np.max([6, self.slope_percent_deviation.max() * 1.5])) subplot.axhline(5, c='red', linestyle='--') subplot.fill_between(self.times, 5, np.max([6, self.slope_percent_deviation.max() * 1.5]), color='red', alpha=0.2) subplot.set_title('Allowable Percent Deviation (red = data unusable)') subplot.set_xlabel('Time (s)') subplot.set_ylabel('% deviation')