Esempio n. 1
0
    def save_animation(self, filename: str = None):
        if self._animation is None:
            return
        self._animation.pause()
        if filename is None:
            filename, format_str = QtWidgets.QFileDialog.getSaveFileName(
                self,
                self.
                tr("Choose a filename to save the animation of this SSU result"
                   ), ".",
                "MPEG-4 Video File (*.mp4);;Html Animation (*.html);;Graphics Interchange Format (*.gif)"
            )
        if filename is None or filename == "":
            return
        progress_dialog = QtWidgets.QProgressDialog(
            self.tr("Saving Animation Frames..."), self.tr("Cancel"), 0, 100,
            self)
        progress_dialog.setWindowTitle("QGrain")
        progress_dialog.setWindowModality(QtCore.Qt.WindowModal)

        def callback(frame_number, total_frames):
            if progress_dialog.wasCanceled():
                raise StopIteration()
            progress_dialog.setValue(int(frame_number / total_frames * 100))
            QtCore.QCoreApplication.processEvents()

        try:
            if filename[-5:] == ".html":
                if not FFMpegWriter.isAvailable():
                    self.show_error(self.tr("FFMpeg is not installed."))
                else:
                    self.show_info(
                        self.
                        tr("Rendering the animation to a html5 video, it will take several minutes."
                           ))
                    html = self._animation.to_html5_video()
                    with open(filename, "w") as f:
                        f.write(html)
            elif filename[-4:] == ".gif":
                if not ImageMagickWriter.isAvailable():
                    self.show_error(self.tr("ImageMagick is not installed."))
                else:
                    self._animation.save(filename,
                                         writer="imagemagick",
                                         fps=10,
                                         progress_callback=callback)
            elif filename[-4:] == ".mp4":
                if not FFMpegWriter.isAvailable():
                    self.show_error(self.tr("FFMpeg is not installed."))
                else:
                    self._animation.save(filename,
                                         writer="ffmpeg",
                                         fps=10,
                                         progress_callback=callback)
        except StopIteration:
            self.logger.info("The saving task was canceled.")
        finally:
            progress_dialog.close()
Esempio n. 2
0
 def save_animation(self):
     if self.last_result is not None:
         filename, format_str = self.file_dialog.getSaveFileName(self, self.tr("Save the animation of this SSU result"), None, self.tr("MPEG-4 Video File (*.mp4);;Graphics Interchange Format (*.gif)"))
         if filename is None or filename == "":
             return
         progress = QProgressDialog(self)
         progress.setRange(0, 100)
         progress.setLabelText(self.tr("Saving Animation [{0} Frames]").format(self.last_result.n_iterations))
         canceled = False
         def save_callback(i, n):
             if progress.wasCanceled():
                 nonlocal canceled
                 canceled = True
                 raise StopIteration()
             progress.setValue((i+1)/n*100)
             QCoreApplication.processEvents()
         self.show_result(self.last_result)
         # plt.rcParams["savefig.dpi"] = 120.0
         if "*.gif" in format_str:
             if not ImageMagickWriter.isAvailable():
                 self.normal_msg.setWindowTitle(self.tr("Error"))
                 self.normal_msg.setText(self.tr("ImageMagick is not installed, please download and install it from its offical website (https://imagemagick.org/index.php)."))
                 self.normal_msg.exec_()
             else:
                 self.animation.save(filename, writer="imagemagick", fps=30, progress_callback=save_callback)
         elif "*.mp4" in format_str:
             if not FFMpegWriter.isAvailable():
                 self.normal_msg.setWindowTitle(self.tr("Error"))
                 self.normal_msg.setText(self.tr("FFMpeg is not installed, please download and install it from its offical website (https://ffmpeg.org/)."))
                 self.normal_msg.exec_()
             else:
                 self.animation.save(filename, writer="ffmpeg", fps=30, progress_callback=save_callback)
         # plt.rcParams["savefig.dpi"] = 300.0
         if not canceled:
             progress.setValue(100)
Esempio n. 3
0
    def __init__(self,
                 filename: str,
                 framerate: float = 30,
                 dpi: float = None,
                 **kwargs):
        r"""
        Args:
            filename (str):
                The filename where the movie is stored. The suffix of this path
                also determines the default movie codec.
            framerate (float):
                The number of frames per second, which determines how fast the
                movie will appear to run.
            dpi (float):
                The resolution of the resulting movie
            \**kwargs:
                Additional parameters are used to initialize
                :class:`matplotlib.animation.FFMpegWriter`.
        """
        self.filename = str(filename)
        self.framerate = framerate
        self.dpi = dpi
        self.kwargs = kwargs

        # test whether ffmpeg is available
        from matplotlib.animation import FFMpegWriter
        if not FFMpegWriter.isAvailable():
            raise RuntimeError('FFMpegWriter is not available. This is most '
                               'likely because a suitable installation of '
                               'FFMpeg was not found. See ffmpeg.org for how '
                               'to install it properly on your system.')

        self._writer = None
Esempio n. 4
0
 def is_available(cls) -> bool:
     """ check whether the movie infrastructure is available
     
     Returns:
         bool: True if movies can be created
     """
     from matplotlib.animation import FFMpegWriter
     return FFMpegWriter.isAvailable()  # type: ignore
Esempio n. 5
0
def _anim_rst(anim, image_path, gallery_conf):
    from matplotlib.animation import FFMpegWriter, ImageMagickWriter
    # output the thumbnail as the image, as it will just be copied
    # if it's the file thumbnail
    fig = anim._fig
    image_path = image_path.replace('.png', '.gif')
    fig_size = fig.get_size_inches()
    thumb_size = gallery_conf['thumbnail_size']
    use_dpi = round(
        min(t_s / f_s for t_s, f_s in zip(thumb_size, fig_size)))
    if FFMpegWriter.isAvailable():
        writer = 'ffmpeg'
    elif ImageMagickWriter.isAvailable():
        writer = 'imagemagick'
    else:
        writer = None
    anim.save(image_path, writer=writer, dpi=use_dpi)
    html = anim._repr_html_()
    if html is None:  # plt.rcParams['animation.html'] == 'none'
        html = anim.to_jshtml()
    html = indent(html, '     ')
    return _ANIMATION_RST.format(html)
Esempio n. 6
0
def create_animation(agent, every_n_steps=1, display_mode='gif', fps=30):
    history = agent.history
    fig = plt.figure(figsize=(11, 6))
    fig.set_tight_layout(True)
    main_rows = gridspec.GridSpec(2,
                                  1,
                                  figure=fig,
                                  top=.9,
                                  left=.05,
                                  right=.95,
                                  bottom=.25)

    def create_top_row_im(i, title='', actions_cmap=False):
        top_row = main_rows[0].subgridspec(1, 5, wspace=.3)
        ax = fig.add_subplot(top_row[i])
        ax.axis('off')
        ax.set_title(title)
        im = ax.imshow(np.zeros((len(history.q_a_frames_spec.ys),
                                 len(history.q_a_frames_spec.xs))),
                       origin='lower')
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="5%", pad=0.05)
        if actions_cmap is True:
            im.set_clim(history.q_a_frames_spec.amin,
                        history.q_a_frames_spec.amax)
            im.set_cmap("RdYlGn")
            cb = fig.colorbar(im, cax=cax)
        else:
            cb = fig.colorbar(im, cax=cax, format='%.3g')
        cb.ax.tick_params(labelsize=8)
        return im

    def create_bottom_row_plot(i, title=''):
        bottom_row = main_rows[1].subgridspec(1, 3)
        ax = fig.add_subplot(bottom_row[i])
        ax.set_title(title)
        return ax

    Q_max_im = create_top_row_im(0, title='Q max')
    Q_std_im = create_top_row_im(1, title='Q standard deviation')
    action_gradients_im = create_top_row_im(2, title="Action Gradients")
    max_action_im = create_top_row_im(3,
                                      title="Action with Q max",
                                      actions_cmap=True)
    actor_policy_im = create_top_row_im(4, title="Policy", actions_cmap=True)

    scores_ax = create_bottom_row_plot(0, title="Scores")
    scores_ax.xaxis.set_major_locator(MaxNLocator(integer=True))
    scores_ax.yaxis.set_major_locator(MaxNLocator(integer=True))
    training_scores_line, = scores_ax.plot([], 'bo', label='training')
    test_scores_line, = scores_ax.plot([], 'ro', label='test')
    scores_ax.set_xlim(1, len(history.training_episodes))
    scores_combined = np.array([e.score for e in history.training_episodes ]+\
                               [e.score for e in history.test_episodes ])
    scores_ax.set_ylim(scores_combined.min(), scores_combined.max())
    scores_ax.set_xlabel('episode')
    scores_ax.set_ylabel('total reward')
    scores_ax.legend(loc='upper left', bbox_to_anchor=(0, -.1))

    training_episode_ax = create_bottom_row_plot(1)
    training_episode_ax.yaxis.set_major_locator(MaxNLocator(integer=True))
    # TODO: get axis names from q_a_grid_spec
    training_episode_position_line, = training_episode_ax.plot(
        [], 'b-', label='position')
    training_episode_velocity_line, = training_episode_ax.plot(
        [], 'm-', label='velocity')
    training_episode_action_line, = training_episode_ax.plot([],
                                                             'r-',
                                                             label='action')
    training_episode_reward_line, = training_episode_ax.plot([],
                                                             'g-',
                                                             label='reward')
    training_episode_ax.set_ylim((-1.1, 1.1))
    training_episode_ax.axes.get_yaxis().set_visible(False)
    #     training_episode_ax.legend(loc='upper left', ncol=2)

    test_episode_ax = create_bottom_row_plot(2)
    test_episode_ax.yaxis.set_major_locator(MaxNLocator(integer=True))
    test_episode_position_line, = test_episode_ax.plot([],
                                                       'b-',
                                                       label='position')
    test_episode_velocity_line, = test_episode_ax.plot([],
                                                       'm-',
                                                       label='velocity')
    test_episode_action_line, = test_episode_ax.plot([], 'r-', label='action')
    test_episode_reward_line, = test_episode_ax.plot([], 'g-', label='reward')
    test_episode_ax.set_ylim((-1.1, 1.1))
    test_episode_ax.axes.get_yaxis().set_visible(False)
    test_episode_ax.legend(loc='upper left', ncol=2, bbox_to_anchor=(-.5, -.1))

    def update(step_idx):
        num_frames = math.ceil(last_step / every_n_steps)
        frame_idx = math.ceil(step_idx / every_n_steps)
        print("Drawing frame: %i/%i, %.2f%%\r"%\
              (frame_idx+1, num_frames, 100*(frame_idx+1)/float(num_frames) ), end='')
        training_episode = history.get_training_episode_for_step(step_idx)
        episode_step_idx = step_idx - training_episode.first_step

        q_a_frames = history.get_q_a_frames_for_step(step_idx)

        Q_max_im.set_data(q_a_frames.Q_max)
        Q_max_im.set_clim(q_a_frames.Q_max.min(), q_a_frames.Q_max.max())
        Q_std_im.set_data(q_a_frames.Q_std)
        Q_std_im.set_clim(q_a_frames.Q_std.min(), q_a_frames.Q_std.max())
        action_gradients_im.set_data(
            q_a_frames.action_gradients.reshape(agent.q_a_frames_spec.ny,
                                                agent.q_a_frames_spec.nx))
        action_gradients_im.set_clim(q_a_frames.action_gradients.min(),
                                     q_a_frames.action_gradients.max())
        max_action_im.set_data(q_a_frames.max_action)
        actor_policy_im.set_data(
            q_a_frames.actor_policy.reshape(agent.q_a_frames_spec.ny,
                                            agent.q_a_frames_spec.nx))

        # Plot scores
        xdata = range(1, training_episode.episode_idx + 1)
        training_scores_line.set_data(xdata, [
            e.score for e in history.training_episodes
        ][:training_episode.episode_idx])
        test_scores_line.set_data(xdata,
                                  [e.score for e in history.test_episodes
                                   ][:training_episode.episode_idx])

        #Plot training episode
        training_episode_ax.set_title(
            "Training episode %i, eps=%.3f, score: %.3f" %
            (training_episode.episode_idx, training_episode.epsilon,
             training_episode.score))

        current_end_idx = episode_step_idx + every_n_steps
        if current_end_idx >= len(training_episode.states):
            current_end_idx = len(training_episode.states) - 1

        training_xdata = range(0, current_end_idx + 1)
        training_episode_ax.set_xlim(
            training_xdata[0],
            training_episode.last_step - training_episode.first_step + 1)
        episode_states = [
            agent.preprocess_state(s) for s in training_episode.states
        ]
        training_episode_position_line.set_data(training_xdata,
                                                [s[0] for s in episode_states
                                                 ][:current_end_idx + 1])
        training_episode_velocity_line.set_data(training_xdata,
                                                [s[1] for s in episode_states
                                                 ][:current_end_idx + 1])
        training_episode_action_line.set_data(
            training_xdata, training_episode.actions[:current_end_idx + 1])
        training_episode_reward_line.set_data(
            training_xdata, training_episode.rewards[:current_end_idx + 1])

        #Plot test episode
        test_episode = history.get_test_episode_for_step(step_idx)
        if test_episode is not None:
            test_episode_ax.set_title(
                "Test episode %i, score: %.3f" %
                (test_episode.episode_idx, test_episode.score))
            test_xdata = range(1, len(test_episode.states) + 1)
            test_episode_ax.set_xlim(test_xdata[0], test_xdata[-1])
            episode_states = [
                agent.preprocess_state(e) for e in test_episode.states
            ]
            test_episode_position_line.set_data(test_xdata,
                                                [s[0] for s in episode_states])
            test_episode_velocity_line.set_data(test_xdata,
                                                [s[1] for s in episode_states])
            test_episode_action_line.set_data(test_xdata, test_episode.actions)
            test_episode_reward_line.set_data(test_xdata, test_episode.rewards)

    last_step = history.training_episodes[-1].last_step + 1
    anim = FuncAnimation(fig,
                         update,
                         interval=1000 / fps,
                         frames=range(0, last_step, every_n_steps))

    if display_mode == 'video' or display_mode == 'video_file':
        from matplotlib.animation import FFMpegWriter
        writer = FFMpegWriter(fps=fps)
        if writer.isAvailable():
            print("Using ffmpeg at '%s'." % writer.bin_path())
        else:
            raise ("FFMpegWriter not available for video output.")
    if display_mode == 'js':
        display(HTML(anim.to_jshtml()))
    elif display_mode == 'video':
        display(HTML(anim.to_html5_video()))
    elif display_mode == 'video_file':
        filename = 'training_animation_%i.mp4' % int(
            datetime.now().timestamp())
        img = anim.save(filename, writer=writer)
        print("\rVideo saved to %s." % filename)
        # import io, base64
        # encoded = base64.b64encode(io.open(filename, 'r+b').read())
        # display(HTML(data='''<video alt="training animation" controls loop autoplay>
        #                 <source src="data:video/mp4;base64,{0}" type="video/mp4" />
        #              </video>'''.format(encoded.decode('ascii'))))
        display(
            HTML(
                data='''<video alt="training animation" controls loop autoplay>
                        <source src="{0}" type="video/mp4" />
                     </video>'''.format(filename)))
    else:
        filename = 'training_animation_%i.gif' % int(
            datetime.now().timestamp())
        img = anim.save(filename, dpi=80, writer='imagemagick')
        display(HTML("<img src='%s'/>" % filename))
    plt.close()