def setup_figure(self): win = self.fig.canvas.window() win.setFixedSize(win.size()) gs = gridspec.GridSpec(1, 2, left=0, right=1, bottom=0, top=0.92, wspace=0.06, width_ratios=(1, 2)) self.ax1 = self.fig.add_subplot(gs[0]) # ax1 # --- # Show frame frame = self.get_frame(self.first_frame) self.img = self.ax1.imshow(frame, cmap='gray') # Scale bar h, w = frame.shape w -= 50 self.ax1.plot([100, 100 + (w / 5)], [h - 80, h - 80], c='k', lw=2) # Show tracking tracking_info = self.get_tracking(self.first_frame) self.heading_vector, = self.ax1.plot(*np.vstack( (tracking_info['fish_centre'], tracking_info['fish_centre'] + (80 * tracking_info['heading_vector']))).T, c='k', lw=1, ls='dotted', zorder=1) self.eye_centres = self.ax1.scatter(*np.vstack( (tracking_info['right_centre'], tracking_info['left_centre'])).T, c=['m', 'g'], s=5, lw=0) self.eye_vectors = [] for p, v, c in ((tracking_info['right_centre'], tracking_info['right_vector'], 'm'), (tracking_info['left_centre'], tracking_info['left_vector'], 'g')): eye_vector, = self.ax1.plot(*np.vstack( (p - (30 * v), p + (30 * v))).T, c=c, lw=1) self.eye_vectors.append(eye_vector) self.tail_points = self.ax1.scatter(*tracking_info['tail_points'].T, c=tracking_info['colors'], s=2, lw=0, zorder=2) self.ax1.axis('off') # ax2 # --- sub_gs = gridspec.GridSpecFromSubplotSpec(3, 1, gs[1], wspace=0, hspace=0.1) self.ax21_r = self.fig.add_subplot(sub_gs[0]) self.ax22 = self.fig.add_subplot(sub_gs[1]) self.ax23 = self.fig.add_subplot(sub_gs[2]) t = np.arange(self.first_frame, self.last_frame + 1) / 500. # --------- # Plot eyes # --------- self.right_eye_data = self.kinematics['right'].apply(np.degrees) self.left_eye_data = self.kinematics['left'].apply(np.degrees) eye_max = np.ceil( max(self.right_eye_data.max(), (-self.left_eye_data).max())) eye_min = np.floor( min(self.right_eye_data.min(), (-self.left_eye_data).min())) eye_range = eye_max - eye_min self.right_eye, = self.ax21_r.plot(t, self.right_eye_data, c='m', lw=1) self.ax21_r.set_ylim(eye_min, eye_min + (2 * eye_range)) self.ax21_l = plt.twinx(self.ax21_r) self.left_eye, = self.ax21_l.plot(t, self.left_eye_data, c='g', lw=1) self.ax21_l.set_ylim(-eye_min - (2 * eye_range), -eye_min) self.ax21_l.text(t[0] + 0.02, self.left_eye_data.iloc[0] - 5, 'L', fontproperties=verysmallfont, verticalalignment='top', color='g') self.ax21_r.text(t[0] + 0.02, self.right_eye_data.iloc[0], 'R', fontproperties=verysmallfont, verticalalignment='bottom', color='m') self.ax21_l.spines['left'].set_bounds(-40, -10) self.ax21_l.set_yticks([-40, -10]) self.ax21_l.set_yticklabels([40, 10], fontproperties=verysmallfont) self.ax21_l.set_yticks(np.arange(-30, -10, 10), minor=True) self.ax21_r.spines['left'].set_bounds(10, 40) self.ax21_r.set_yticks([10, 40]) self.ax21_r.set_yticklabels([ 10, ], fontproperties=verysmallfont) self.ax21_r.set_yticks(np.arange(20, 40, 10), minor=True) title1 = self.ax21_r.set_title(u'Eye angle (\u00b0)', loc='left', fontproperties=verysmallfont) title1.set_position((0.005, 0.9)) # Axis limits for ax in (self.ax21_r, self.ax21_l): ax.set_xlim(t[0], t[-1]) open_ax(ax) ax.set_xticks([]) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_color('0.5') ax.spines['left'].set_linewidth(1) ax.tick_params(axis='y', which='both', color='0.5', length=3, width=1, labelcolor='0.5', pad=1) ax.tick_params(axis='y', which='minor', length=2, width=1) # -------------------- # Plot tail kinematics # -------------------- self.tail_kinematics = self.kinematics.loc[:, self.tail_columns].applymap( np.degrees) plot_tail_kinematics(self.ax22, self.tail_kinematics, k_max=90) title2 = self.ax22.set_title('Rostro-caudal tail angle', loc='left', fontproperties=verysmallfont) title2.set_position((0.005, 0.65)) # Create color bar (l, b, w, h) = self.ax22.get_position().bounds cbar = self.fig.add_axes( (l + (w * 0.4), b + (h * 0.8), w * 0.05, h * 0.1)) cm = plt.cm.ScalarMappable(cmap='RdBu') cm.set_array(np.linspace(-1, 1, 2)) cb = self.fig.colorbar(cm, cax=cbar, orientation='horizontal', ticks=[]) cb.outline.set_linewidth(1) cbar.text(-0.1, 0, u'90\u00b0(L)', fontproperties=verysmallfont, horizontalalignment='right') cbar.text(1.1, 0, u'90\u00b0(R)', fontproperties=verysmallfont, horizontalalignment='left') # Axis label self.ax22.text(-0.03, 0.05, 'Ro', fontproperties=verysmallfont, horizontalalignment='right', verticalalignment='top') self.ax22.text(-0.03, 1, 'Ca', fontproperties=verysmallfont, horizontalalignment='right', verticalalignment='bottom') # --------------- # Plot tail angle # --------------- ps = generate_reconstructed_points( self.kinematics.loc[:, self.tail_columns].values, 0) self.tip_angle_data = np.degrees(np.arcsin(ps[:, 1, -1] / 50.)) self.tip_angle, = self.ax23.plot(t, self.tip_angle_data, c='k', lw=0.5) # Axis limits open_ax(self.ax23) self.ax23.set_xlim(t[0], t[-1]) self.ax23.set_xticks([]) self.ax23.spines['bottom'].set_visible(False) self.ax23.set_ylim(-50, 30) self.ax23.plot([t[-20] - 0.5, t[-20]], [-45, -45], c='k', lw=2) self.ax23.set_yticks([-30, 0, 30]) self.ax23.spines['left'].set_bounds(-30, 30) self.ax23.spines['left'].set_color('0.5') self.ax23.spines['left'].set_linewidth(1) self.ax23.tick_params(axis='y', which='both', color='0.5', length=3, width=1, labelcolor='0.5', pad=1) self.ax23.set_yticklabels([-30, 0, 30], fontproperties=verysmallfont) self.ax23.tick_params(axis='y', which='minor', length=2, width=1) self.ax23.set_yticks(np.arange(-20, 30, 10), minor=True) title3 = self.ax23.set_title(u'Tail tip angle (\u00b0)', loc='left', fontproperties=verysmallfont) title3.set_position((0.005, 0.78))
for cluster, bout_idxs, average in zip(cluster_bouts, cluster_bout_idxs, cluster_averages): distances = [dtw(average, bout, fs=500., bandwidth=0.006) for bout in cluster] idx_nearest = np.argsort(distances)[:10] representative_indices.append(bout_idxs[idx_nearest]) bout_idx = bout_idxs[idx_nearest[0]] representative_kinematics = capture_strikes.get_bout(bout_index=bout_idx).values[12:37] exemplars_kinematics.append(representative_kinematics) representative_indices = np.concatenate(representative_indices) exemplar_info = capture_strike_info.loc[representative_indices] exemplar_info.to_csv(os.path.join(output_directory, 'figure5', 'exemplar_strikes.csv'), index=True) # Plot tail kinematics and tail series of representative bouts # ------------------------------------------------------------ fig, rows = plt.subplots(2, 2, figsize=(2, 2), dpi=300) for i in range(2): ax1 = rows[0][i] ax2 = rows[1][i] k = exemplars_kinematics[i] if i == 0: # flip the attack swim kinematics = -k else: kinematics = k trajectory = map_data(whiten_data(kinematics, mean, std), eigenfish)[:, :3] pseudo_bout = trajectory_to_bout(trajectory, eigenfish[:3], mean, std) ps = generate_reconstructed_points(pseudo_bout, 90) plot_reconstructed_points(ax1, ps, lw=1) ax1.axis('equal') ax1.axis('off') plot_tail_kinematics(ax2, kinematics, fs=500., k_max=np.radians(70)) save_fig(fig, 'figure5', 'representative_bouts')
mean, std = np.load(os.path.join(data_directory, 'tail_statistics.npy')) n_components = 3 if __name__ == "__main__": fig_height = 0.9108 * 2 fig_width = n_components * fig_height * 0.618 * 2 fig = plt.figure(figsize=(fig_width, fig_height)) gs = gridspec.GridSpec(1, n_components, left=0, right=1, bottom=0.05, top=0.95, wspace=0) axes = [fig.add_subplot(gs[i]) for i in range(n_components)] for pc, ax in enumerate(axes): eigenseries = np.array( [eigenfish[pc] * i for i in np.linspace(0, 10, 50)]) eigenseries = (eigenseries * std) + mean tail_points = generate_reconstructed_points(eigenseries, 90) plot_reconstructed_points(ax, tail_points, color='binary', lw=2) ax.set_xlim(-50, 0) ax.axis('equal') ax.axis('off') # plt.show() save_fig(fig, 'figure1', 'eigenfish')
ax0.set_xticks([]) ax0.set_yticklabels([]) for spine in ('top', 'right', 'bottom'): ax0.spines[spine].set_visible(False) ax0.spines['left'].set_color('0.5') ax0.tick_params(axis='y', color='0.5') # Tail kinematics plot_tail_kinematics(ax1, np.degrees(representative_kinematics), ax_lim=(0, 0.18), k_max=120) # Pseudo-bout k = (np.dot(representative_transformed, eigenfish[:3]) * tail_stats[1]) + tail_stats[0] ps = generate_reconstructed_points(k, 90) plot_reconstructed_points(ax2, ps[:90], lw=1, c_lim=(0, 0.18)) ax2.axis('equal') ax2.axis('off') # plt.show() save_fig(fig, 'figure3', name, 'png') plt.close(fig) representative_bouts = exemplars.loc[representative_bout_indices] representative_bouts.to_csv(os.path.join(experiment.subdirs['analysis'], 'clustering', 'representative_bouts.csv'), index=True)
eigenfish_path = os.path.join(experiment.directory, 'analysis', 'behaviour_space', 'eigenfish.npy') tail_statistics_path = os.path.join(experiment.directory, 'analysis', 'behaviour_space', 'tail_statistics.npy') eigenfish = np.load(eigenfish_path) mean, std = np.load(tail_statistics_path) kinematics = data['kinematics'] first_frame, last_frame = data['first_frame'], data['last_frame'] tail_columns = [col for col in kinematics.columns if (col[0] == 'k')] tail = kinematics.loc[first_frame:last_frame, tail_columns].values whitened = whiten_data(tail, mean, std) transformed = map_data(whitened, eigenfish[:3]) reconstructed = generate_reconstructed_points( np.dot(transformed, eigenfish[:3]) * std + mean, 0) colors = TimeMap(0, 0.2).map(np.linspace(-0.2, 0.2, 101)) colors = np.array(colors) colors[:50, -1] = np.linspace(0, 1, 50) transformed_plot = AnimatedTransformed(range(first_frame, last_frame), fps=50, figsize=(4, 3), **data) transformed_plot.setup_figure() # transformed_plot.show_frame(last_frame) # transformed_plot.play() transformed_plot.save(os.path.join(output_directory, 'video2_mpg'))
0.05, 'Ro', fontproperties=tinyfont, horizontalalignment='right', verticalalignment='top') ax2.text(-0.03, 1, 'Ca', fontproperties=tinyfont, horizontalalignment='right', verticalalignment='bottom') # --------------- # Plot tail angle # --------------- ps = generate_reconstructed_points(kinematics.loc[:, tail_columns].values, 0) tip_angle = np.degrees(np.arcsin(ps[:, 1, -1] / 50.)) ax3.plot(t, tip_angle, c='k', lw=1) for idx, bout_info in example_bouts.iterrows(): t_ = np.arange(bout_info.start, bout_info.end + 1) / 500. ax3.fill_between(t_, np.ones((len(t_), )) * (-40), np.ones((len(t_), )) * 20, facecolor='0.8') # Axis limits open_ax(ax3) ax3.set_xlim(t[0], t[-1]) ax3.set_xticks([]) ax3.spines['bottom'].set_visible(False)
|__w3__| """ total_width = 3.5 figures = [] for idx, bout_info in example_bouts.iterrows(): bout = kinematics.loc[bout_info.start:bout_info.end] transformed = np.dot((bout.values - mean) / std, eigenfish.T) reconstructed = (np.dot(transformed, eigenfish) * std) + mean w1 = 0.7 * len(bout) / 50. ps = generate_reconstructed_points(reconstructed, 90) ax2_xmin = np.floor(ps[:, 0, :].min()) ax2_xmax = np.ceil(ps[:, 0, :].max()) ax2_width = ax2_xmax - ax2_xmin h = 1. w2 = ax2_width / 50. spacing = 0.05 width = w1 + spacing + w2 wpad = spacing / width fig1 = plt.figure(figsize=(width, 1)) gs1 = gridspec.GridSpec(1, 2, width_ratios=(w1, w2),
def setup_figure(self): gs = gridspec.GridSpec(1, 2, left=0, right=1, bottom=0, top=1, wspace=0, width_ratios=(2, 3)) self.ax1 = self.fig.add_subplot(gs[0]) win = self.fig.canvas.window() win.setFixedSize(win.size()) # ax1 # --- # Show frame frame = self.get_frame(self.first_frame) self.img = self.ax1.imshow(frame, cmap='gray') # 300 pixels = 5 mm -> 120 pixels = 2 mm self.ax1.plot([100, 220], [870, 870], c='k') # Show tracking tracking_info = self.get_tracking(self.first_frame) # Side self.pitch_vector, = self.ax1.plot(*np.vstack( (tracking_info['side_centre'] - (50 * tracking_info['tail_vector']), tracking_info['side_centre'] + (150 * tracking_info['tail_vector']))).T, zorder=1, c='r', lw=0.5) self.elevation_vector, = self.ax1.plot(*np.vstack( (tracking_info['side_centre'] - (50 * tracking_info['head_vector']), tracking_info['side_centre'] + (50 * tracking_info['head_vector']))).T, zorder=2, c='r', lw=0.5) self.depression_vector, = self.ax1.plot(*np.vstack( (tracking_info['head_midpoint'], tracking_info['hyoid'])).T, zorder=2, c='c', lw=0.5) self.side_points = self.ax1.scatter(*np.vstack( (tracking_info['side_centre'], tracking_info['head_midpoint'])).T, c=['r', 'c'], s=3, zorder=2, lw=0) self.heading_vector, = self.ax1.plot(*np.vstack( (tracking_info['fish_centre'], tracking_info['fish_centre'] + (100 * tracking_info['heading_vector']))).T, c='k', lw=0.5, ls='dotted', zorder=1) self.tail_points = self.ax1.scatter(*tracking_info['tail_points'].T, c=tracking_info['colors'], s=1, lw=0, zorder=2) self.ax1.axis('off') # ax2 # --- sub_gs = gridspec.GridSpecFromSubplotSpec(4, 1, gs[1], hspace=0.2) self.ax21 = self.fig.add_subplot(sub_gs[0]) self.ax22 = self.fig.add_subplot(sub_gs[1]) self.ax23 = self.fig.add_subplot(sub_gs[2]) self.ax24 = self.fig.add_subplot(sub_gs[3]) t = np.arange(self.first_frame, self.last_frame + 1) / 500. # Plot jaw self.depression, = self.ax21.plot(t, self.kinematics['depression'], c='k', lw=1) self.elevation, = self.ax21.plot(t, self.kinematics['elevation'].apply( np.degrees), c='0.5', lw=1) ymax = self.kinematics['elevation'].apply(np.degrees).max() self.ax21.text(t[0] + 0.02, ymax, 'Jaw depression', fontproperties=tinyfont, verticalalignment='top', color='k') self.ax21.text(t[0] + 0.02, ymax - 3, 'Cranial elevation', fontproperties=tinyfont, verticalalignment='top', color='0.5') # Plot tail kinematics self.tail_kinematics = self.kinematics.loc[:, self.tail_columns].applymap( np.degrees) plot_tail_kinematics(self.ax22, self.tail_kinematics, k_max=90) title2 = self.ax22.set_title('Rostro-caudal tail angle', loc='left', fontproperties=tinyfont) title2.set_position((0.005, 0.62)) # Plot tail angle ps = generate_reconstructed_points( self.kinematics.loc[:, self.tail_columns].values, 0) self.tip_angle_data = np.degrees(np.arcsin(ps[:, 1, -1] / 50.)) self.tip_angle, = self.ax23.plot(t, self.tip_angle_data, c='k', lw=1) self.ax23.set_ylim(-45, 20) self.ax23.text(t[0] + 0.02, self.tip_angle_data.max() - 5, 'Tail tip angle', fontproperties=tinyfont, verticalalignment='bottom', color='k') # Plot pitch self.pitch, = self.ax24.plot(t, self.kinematics['fish_elevation'].apply( np.degrees), c='k', lw=1) self.ax24.text(t[0] + 0.02, self.kinematics['fish_elevation'].apply( np.degrees).max(), 'Pitch', fontproperties=tinyfont, verticalalignment='top', color='k') # Inset # ----- fig_width, fig_height = self.fig.get_size_inches() ratio = float(fig_width) / fig_height x0, y0, x1, y1 = self.ax1.get_position().bounds w = 0.4 * (x1 - x0) y = (y1 - y0) / 2. h = ratio * w / 2.6 self.ax3 = self.fig.add_axes((x1 - (1.2 * w), y - (h / 2.), w, h)) frame = self.get_frame(self.first_frame, head_stabilise=True) self.inset = self.ax3.imshow(frame, cmap='gray') self.ax3.set_xticks([]) self.ax3.set_yticks([]) # Set axis limits for ax in (self.ax21, self.ax23, self.ax24): ax.set_xlim(t[0], t[-1]) ax.axis('off')