def debug_rotation(ast_trial): """ Plot what the values look like when rotated, debugging tool """ try: if ast_trial.is_ast_trial: rotated_points = AsteriskCalculations.rotate_points( ast_trial.poses, AsteriskCalculations.rotations[ ast_trial.trial_translation]) else: rotated_points = ast_trial except: rotated_points = ast_trial # plot the points x = pd.Series.to_list(rotated_points["x"].dropna()) y = pd.Series.to_list(rotated_points["y"].dropna()) plt.plot(x, y, color="xkcd:dark orange") # plot the target line tar_x, tar_y = AsteriskPlotting.get_c(100) plt.plot(tar_x, tar_y, color="xkcd:dark blue") # show plot plt.show()
def calc_max_area_region(ast_trial, percent_window_size=0.2): """ Calculates the area of max error by sliding a window of 20% normalized length along the target line Seems that 10% is too small in regions of fast movement """ # TODO: cheating again by rotating points... what about negative values? points = AsteriskCalculations.rotate_points(ast_trial.poses, AsteriskCalculations.rotations[ast_trial.trial_translation]) t_x, t_y = AsteriskPlotting.get_c(100) # TODO: maybe make target_line a pandas dataframe targets = np.column_stack((t_x, t_y)) #AsteriskMetrics.debug_rotation(points) # prepare bound size bound_size = 0.5 * (percent_window_size * ast_trial.total_distance) x_center = bound_size + 0 # just being explicit here -> x_min is 0 x_max = 2 * bound_size max_area_calculated = 0 x_center_at_max = x_center while x_max <= ast_trial.total_distance: # print(f"Now at {x_center} || {x_max}/{ast_trial.total_distance}") bounded_points = AsteriskCalculations.get_points_df(points, x_center, bound_size) b_x = pd.Series.to_list(bounded_points["x"].dropna()) b_y = pd.Series.to_list(bounded_points["y"].dropna()) bounded_points_not_df = np.column_stack((b_x, b_y)) target_points = AsteriskCalculations.get_points_list(targets, x_center, bound_size) try: area_calculated = sm.area_between_two_curves(bounded_points_not_df, target_points) except ValueError or IndexError: # usually this triggers if there aren't enough points (more than one) in the window # if there aren't enough points, make enough points! try: area_calculated = AsteriskCalculations.interpolate_points(points, x_center, bounded_points, bound_size, target_points) print("Successful interpolation!") except Exception as e: print("Interpolation Failed.") print(e) # if not points were found at all in this region, depending on bound size area_calculated = 0 x_center = x_center + 0.1 * bound_size # want to step in 1% increments x_max = x_center + bound_size if np.abs(area_calculated) > max_area_calculated: max_area_calculated = np.abs(area_calculated) x_center_at_max = x_center # percentage along the target_line line that the center of max error was located x_center_perc = x_center_at_max / 0.5 # gives us percentage along the full target line, for easy comparing # x_center_at_max_r = AsteriskMetrics.rotate_point([x_center_at_max, 0], # -1 * AsteriskMetrics.rotations[ast_trial.trial_translation]) # print(f"results: {max_area_calculated}, {x_center_perc}") return max_area_calculated, x_center_perc
def plot_all_target_lines(self, order_of_colors): """ Plot all target lines on a plot for easy reference :param order_of_colors: """ x_a, y_a = aplt.get_a() x_b, y_b = aplt.get_b() x_c, y_c = aplt.get_c() x_d, y_d = aplt.get_d() x_e, y_e = aplt.get_e() x_f, y_f = aplt.get_f() x_g, y_g = aplt.get_g() x_h, y_h = aplt.get_h() ideal_xs = [x_a, x_b, x_c, x_d, x_e, x_f, x_g, x_h] ideal_ys = [y_a, y_b, y_c, y_d, y_e, y_f, y_g, y_h] for i in range(8): plt.plot(ideal_xs[i], ideal_ys[i], color=order_of_colors[i], label='ideal', linestyle='--')
def plot_orientation_errors(self, translation, subject=None, rotation="n", show_plot=True, save_plot=False): """ line plot of orientation error throughout a trial for a specific direction :param translation: the type of translation :param subject: list of subjects. If none is provided, uses all of them :param rotation: type of rotation. Defaults to "n" :param show_plot: flag to show plot. Default is true :param save_plot: flat to save plot as a file. Default is False """ if subject: trials = self._get_ast_dir(translation, subject, rotation) else: trials = self._get_ast_dir(translation, self.subjects_containing, rotation) # if self.averages and incl_avg: # TODO: have an option to include the average? # for a in self.averages: # if a.trial_translation==direction_label and a.trial_rotation==rotation_label: # trials.append(a) for t in trials: rot_err = t.calc_rot_err() # currently using the get_c function to generate a normalized set of x values to use as x values x, _ = aplt.get_c(len(rot_err)) # will need to multiply by 2 to get it to go to 1.0 instead of 0.5 plt.plot(2*x, rot_err, label=f"Orientation Err {t.subject}, trial {t.trial_num}") if save_plot: if subject: plt.savefig(f"pics/angerror_{self.hand.get_name()}_{subject}_{translation}_{rotation}.jpg", format='jpg') else: plt.savefig(f"pics/angerror_{self.hand.get_name()}_all_{translation}_{rotation}.jpg", format='jpg') # name -> tuple: subj, hand names print("Figure saved.") print(" ") if show_plot: plt.legend() plt.show()
def check_no_backtracking(data, translation_label, threshold=5, debug_rotation=False): """ True if no (or little) backtracking, False is there is parameters ---------- - data - dataframe, not normalized yet - threshold - how much backtracking to allow, default is 10 mm returns ------- - decision - (True/False that there's no significant backtracking) - (the most backtracking, threshold) - provided for debugging, when True provides the highest cumulated backtrack TODO: test this one more thoroughly! """ # convert to mm data = data * [1., 1., 1., 1000., 1000., 1000., 1., 1000.] data = data.round(4) # rotate everything to c direction rotated_df = AsteriskCalculations.rotate_points( data, AsteriskCalculations.rotations[translation_label]) if debug_rotation: # plot the points x = pd.Series.to_list(rotated_df["x"].dropna()) y = pd.Series.to_list(rotated_df["y"].dropna()) plt.plot(x, y, color="xkcd:dark orange") # plot the target line tar_x, tar_y = AsteriskPlotting.get_c(100) plt.plot(tar_x * 100, tar_y * 100, color="xkcd:dark blue") # show plot plt.show() # calculate the delta x between each point dxs = [] # hold the delta x vals prev_x = 0 for p in rotated_df.iterrows(): x = p[1]['x'] dx = x - prev_x dxs.append(dx) prev_x = x rotated_df["dx"] = dxs # for those in the wrong direction, see how much accumulates and how far they get c_val = 0 # variable which stores cumulative values max_c_val = 0 for p in rotated_df.iterrows(): if p[1]["dx"] < 0: c_val = c_val + p[1]["dx"] if c_val > threshold: return False, (c_val, threshold) if abs(c_val) > abs(max_c_val): max_c_val = c_val else: c_val = 0 print(f"c:{c_val} for {p[1]['x']}, {p[1]['dx']}") # if we went through the entire path and found no significant backtracking, then True! return True, (c_val, threshold)