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')
Exemple #4
0
        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'))
Exemple #6
0
             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')