Example #1
0
class player_base:
    r"""
An instance of this class controls the exploration of a fractal.

:param display: a function which, given a zoom level and possibly its new specification, displays it on the board
  """

    #==================================================================================================

    def __init__(self, display: Callable[[int, Any], None], **ka):
        def frames():
            self.select(None)
            self.setrunning(False)
            yield None
            while True:
                yield self.level

        self.level = -1
        self.anim = FuncAnimation(
            self.board,
            (lambda i: None if i is None else self.show_precision(display(i))),
            frames,
            init_func=(lambda: None),
            repeat=False,
            **ka)

    def setrunning(self, b: bool = None):
        r"""Sets the running state of the animation to *b* (if :const:`None`, the inverse of current running state)."""
        if b is None: b = not self.running
        self.running = b
        if b: self.anim.resume()
        else: self.anim.pause()
        self.show_running(b)

    def show_running(self, b: bool):
        r"""Shows the current running state as *b*. This implementation raises an error."""
        raise NotImplementedError()

    def show_precision(self, p: int):
        r"""Shows the current precision as *p*. This implementation raises an error."""
        raise NotImplementedError()

    def select(self, bounds: Union[Tuple[Tuple[float, float],
                                         Tuple[float, float]], None]):
        r"""Pushes a new level in the animation at the current level plus one. This implementation raises an error."""
        raise NotImplementedError()
class BoundedEquationService(
        DifferentialEquationService[BoundedEquationMetadata], ABC):
    __animation: Optional[FuncAnimation] = None
    __is_animation_playing: bool = False

    def __init__(self, main_figure: Figure):
        super().__init__(main_figure)

    def render_current_solution(self):
        self.clear_figure()
        self.clear_animation()
        K, N = self.solution.shape
        time_domain = np.linspace(0, self.metadata.time, K)
        space_domain = np.linspace(0, self.metadata.length, N)
        x, t = np.meshgrid(space_domain, time_domain)
        ax = self.main_figure.add_subplot(projection='3d')
        ax.set_xlabel('x [length]')
        ax.set_ylabel('t [time]')
        ax.set_zlabel('u(x, t)')
        surf = ax.plot_surface(x,
                               t,
                               self.solution,
                               cmap=cm.coolwarm,
                               linewidth=0,
                               antialiased=False)
        self.main_figure.colorbar(surf, shrink=0.5, aspect=5)

    def generate_animation(self):
        self.clear_figure()
        K, N = self.solution.shape
        ax = self.main_figure.add_subplot()
        Axes.set_xlim(ax, left=0, right=self.metadata.length)
        Axes.set_ylim(ax,
                      bottom=np.min(self.solution),
                      top=np.max(self.solution))
        ax.set_xlabel("x [length]")
        ax.set_ylabel("u(x, t)")
        ax.set_title("Solution: u(x, t)")
        space_domain = np.linspace(0, self.metadata.length,
                                   self.metadata.samples)
        line, = ax.plot(space_domain, self.solution[0], "-o", markersize=4)
        time_text = ax.text(0.82, 0.92, '', transform=ax.transAxes)
        dt = self.metadata.time / K

        def update_plot(k: int):
            line.set_ydata(self.solution[k])
            time_text.set_text("t = %.3f" % (k * dt))
            return line, time_text

        self.__animation = FuncAnimation(self.main_figure,
                                         update_plot,
                                         frames=K,
                                         blit=True,
                                         interval=20)

    def toggle_animation(self):
        if not self.__animation:
            self.generate_animation()
            self.__is_animation_playing = True
        elif self.is_animation_playing():
            self.__animation.pause()
            self.__is_animation_playing = False
        else:
            self.__animation.resume()
            self.__is_animation_playing = True

    def is_animation_playing(self):
        return self.__is_animation_playing

    def export_solution(self, table_path: str):
        K, N = self.solution.shape
        time_domain = np.linspace(0, self.metadata.time, K)
        space_domain = np.linspace(0, self.metadata.length, N)
        workbook = Workbook()
        worksheet = workbook.active
        worksheet.cell(1, 2, "x →")
        for i in range(N):
            worksheet.cell(1, 3 + i, space_domain[i])
        worksheet.write(2, 1, "t ↓")
        for k in range(K):
            worksheet.write(3 + k, 1, time_domain[k])
        for k in range(K):
            for i in range(N):
                worksheet.write(k + 3, i + 3, self.solution[k, i])
        workbook.save(table_path)

    def clear_animation(self):
        if self.__animation:
            self.__animation.pause()
            self.__animation = None
            self.__is_animation_playing = False
            self.main_figure.clf()