Source code for manim.mobject.table

r"""Mobjects representing tables.

Examples
--------

.. manim:: TableExamples
    :save_last_frame:

    class TableExamples(Scene):
        def construct(self):
            t0 = Table(
                [["First", "Second"],
                ["Third","Fourth"]],
                row_labels=[Text("R1"), Text("R2")],
                col_labels=[Text("C1"), Text("C2")],
                top_left_entry=Text("TOP"))
            t0.add_highlighted_cell((2,2), color=GREEN)
            x_vals = np.linspace(-2,2,5)
            y_vals = np.exp(x_vals)
            t1 = DecimalTable(
                [x_vals, y_vals],
                row_labels=[MathTex("x"), MathTex("f(x)")],
                include_outer_lines=True)
            t1.add(t1.get_cell((2,2), color=RED))
            t2 = MathTable(
                [["+", 0, 5, 10],
                [0, 0, 5, 10],
                [2, 2, 7, 12],
                [4, 4, 9, 14]],
                include_outer_lines=True)
            t2.get_horizontal_lines()[:3].set_color(BLUE)
            t2.get_vertical_lines()[:3].set_color(BLUE)
            t2.get_horizontal_lines()[:3].set_z_index(1)
            cross = VGroup(
                Line(UP + LEFT, DOWN + RIGHT),
                Line(UP + RIGHT, DOWN + LEFT))
            a = Circle().set_color(RED).scale(0.5)
            b = cross.set_color(BLUE).scale(0.5)
            t3 = MobjectTable(
                [[a.copy(),b.copy(),a.copy()],
                [b.copy(),a.copy(),a.copy()],
                [a.copy(),b.copy(),b.copy()]])
            t3.add(Line(
                t3.get_corner(DL), t3.get_corner(UR)
            ).set_color(RED))
            vals = np.arange(1,21).reshape(5,4)
            t4 = IntegerTable(
                vals,
                include_outer_lines=True
            )
            g1 = Group(t0, t1).scale(0.5).arrange(buff=1).to_edge(UP, buff=1)
            g2 = Group(t2, t3, t4).scale(0.5).arrange(buff=1).to_edge(DOWN, buff=1)
            self.add(g1, g2)
"""

from __future__ import annotations

__all__ = [
    "Table",
    "MathTable",
    "MobjectTable",
    "IntegerTable",
    "DecimalTable",
]


import itertools as it
from typing import Callable, Iterable, Sequence

from manim.mobject.geometry.line import Line
from manim.mobject.geometry.polygram import Polygon
from manim.mobject.geometry.shape_matchers import BackgroundRectangle
from manim.mobject.text.numbers import DecimalNumber, Integer
from manim.mobject.text.tex_mobject import MathTex
from manim.mobject.text.text_mobject import Paragraph

from .. import config
from ..animation.animation import Animation
from ..animation.composition import AnimationGroup
from ..animation.creation import Create, Write
from ..animation.fading import FadeIn
from ..mobject.types.vectorized_mobject import VGroup, VMobject
from ..utils.color import BLACK, YELLOW, ManimColor, ParsableManimColor
from .utils import get_vectorized_mobject_class


[docs]class Table(VGroup): """A mobject that displays a table on the screen. Parameters ---------- table A 2D array or list of lists. Content of the table has to be a valid input for the callable set in ``element_to_mobject``. row_labels List of :class:`~.VMobject` representing the labels of each row. col_labels List of :class:`~.VMobject` representing the labels of each column. top_left_entry The top-left entry of the table, can only be specified if row and column labels are given. v_buff Vertical buffer passed to :meth:`~.Mobject.arrange_in_grid`, by default 0.8. h_buff Horizontal buffer passed to :meth:`~.Mobject.arrange_in_grid`, by default 1.3. include_outer_lines ``True`` if the table should include outer lines, by default False. add_background_rectangles_to_entries ``True`` if background rectangles should be added to entries, by default ``False``. entries_background_color Background color of entries if ``add_background_rectangles_to_entries`` is ``True``. include_background_rectangle ``True`` if the table should have a background rectangle, by default ``False``. background_rectangle_color Background color of table if ``include_background_rectangle`` is ``True``. element_to_mobject The :class:`~.Mobject` class applied to the table entries. by default :class:`~.Paragraph`. For common choices, see :mod:`~.text_mobject`/:mod:`~.tex_mobject`. element_to_mobject_config Custom configuration passed to :attr:`element_to_mobject`, by default {}. arrange_in_grid_config Dict passed to :meth:`~.Mobject.arrange_in_grid`, customizes the arrangement of the table. line_config Dict passed to :class:`~.Line`, customizes the lines of the table. kwargs Additional arguments to be passed to :class:`~.VGroup`. Examples -------- .. manim:: TableExamples :save_last_frame: class TableExamples(Scene): def construct(self): t0 = Table( [["This", "is a"], ["simple", "Table in \\n Manim."]]) t1 = Table( [["This", "is a"], ["simple", "Table."]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) t1.add_highlighted_cell((2,2), color=YELLOW) t2 = Table( [["This", "is a"], ["simple", "Table."]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")], top_left_entry=Star().scale(0.3), include_outer_lines=True, arrange_in_grid_config={"cell_alignment": RIGHT}) t2.add(t2.get_cell((2,2), color=RED)) t3 = Table( [["This", "is a"], ["simple", "Table."]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")], top_left_entry=Star().scale(0.3), include_outer_lines=True, line_config={"stroke_width": 1, "color": YELLOW}) t3.remove(*t3.get_vertical_lines()) g = Group( t0,t1,t2,t3 ).scale(0.7).arrange_in_grid(buff=1) self.add(g) .. manim:: BackgroundRectanglesExample :save_last_frame: class BackgroundRectanglesExample(Scene): def construct(self): background = Rectangle(height=6.5, width=13) background.set_fill(opacity=.5) background.set_color([TEAL, RED, YELLOW]) self.add(background) t0 = Table( [["This", "is a"], ["simple", "Table."]], add_background_rectangles_to_entries=True) t1 = Table( [["This", "is a"], ["simple", "Table."]], include_background_rectangle=True) g = Group(t0, t1).scale(0.7).arrange(buff=0.5) self.add(g) """ def __init__( self, table: Iterable[Iterable[float | str | VMobject]], row_labels: Iterable[VMobject] | None = None, col_labels: Iterable[VMobject] | None = None, top_left_entry: VMobject | None = None, v_buff: float = 0.8, h_buff: float = 1.3, include_outer_lines: bool = False, add_background_rectangles_to_entries: bool = False, entries_background_color: ParsableManimColor = BLACK, include_background_rectangle: bool = False, background_rectangle_color: ParsableManimColor = BLACK, element_to_mobject: Callable[ [float | str | VMobject], VMobject, ] = Paragraph, element_to_mobject_config: dict = {}, arrange_in_grid_config: dict = {}, line_config: dict = {}, **kwargs, ): self.row_labels = row_labels self.col_labels = col_labels self.top_left_entry = top_left_entry self.row_dim = len(table) self.col_dim = len(table[0]) self.v_buff = v_buff self.h_buff = h_buff self.include_outer_lines = include_outer_lines self.add_background_rectangles_to_entries = add_background_rectangles_to_entries self.entries_background_color = ManimColor(entries_background_color) self.include_background_rectangle = include_background_rectangle self.background_rectangle_color = ManimColor(background_rectangle_color) self.element_to_mobject = element_to_mobject self.element_to_mobject_config = element_to_mobject_config self.arrange_in_grid_config = arrange_in_grid_config self.line_config = line_config for row in table: if len(row) == len(table[0]): pass else: raise ValueError("Not all rows in table have the same length.") super().__init__(**kwargs) mob_table = self._table_to_mob_table(table) self.elements_without_labels = VGroup(*it.chain(*mob_table)) mob_table = self._add_labels(mob_table) self._organize_mob_table(mob_table) self.elements = VGroup(*it.chain(*mob_table)) if len(self.elements[0].get_all_points()) == 0: self.elements.remove(self.elements[0]) self.add(self.elements) self.center() self.mob_table = mob_table self._add_horizontal_lines() self._add_vertical_lines() if self.add_background_rectangles_to_entries: self.add_background_to_entries(color=self.entries_background_color) if self.include_background_rectangle: self.add_background_rectangle(color=self.background_rectangle_color)
[docs] def _table_to_mob_table( self, table: Iterable[Iterable[float | str | VMobject]], ) -> list: """Initilaizes the entries of ``table`` as :class:`~.VMobject`. Parameters ---------- table A 2D array or list of lists. Content of the table has to be a valid input for the callable set in ``element_to_mobject``. Returns -------- List List of :class:`~.VMobject` from the entries of ``table``. """ return [ [ self.element_to_mobject(item, **self.element_to_mobject_config) for item in row ] for row in table ]
[docs] def _organize_mob_table(self, table: Iterable[Iterable[VMobject]]) -> VGroup: """Arranges the :class:`~.VMobject` of ``table`` in a grid. Parameters ---------- table A 2D iterable object with :class:`~.VMobject` entries. Returns -------- :class:`~.VGroup` The :class:`~.VMobject` of the ``table`` in a :class:`~.VGroup` already arranged in a table-like grid. """ help_table = VGroup() for i, row in enumerate(table): for j, _ in enumerate(row): help_table.add(table[i][j]) help_table.arrange_in_grid( rows=len(table), cols=len(table[0]), buff=(self.h_buff, self.v_buff), **self.arrange_in_grid_config, ) return help_table
[docs] def _add_labels(self, mob_table: VGroup) -> VGroup: """Adds labels to an in a grid arranged :class:`~.VGroup`. Parameters ---------- mob_table An in a grid organized class:`~.VGroup`. Returns -------- :class:`~.VGroup` Returns the ``mob_table`` with added labels. """ if self.row_labels is not None: for k in range(len(self.row_labels)): mob_table[k] = [self.row_labels[k]] + mob_table[k] if self.col_labels is not None: if self.row_labels is not None: if self.top_left_entry is not None: col_labels = [self.top_left_entry] + self.col_labels mob_table.insert(0, col_labels) else: # Placeholder to use arrange_in_grid if top_left_entry is not set. # Import OpenGLVMobject to work with --renderer=opengl dummy_mobject = get_vectorized_mobject_class()() col_labels = [dummy_mobject] + self.col_labels mob_table.insert(0, col_labels) else: mob_table.insert(0, self.col_labels) return mob_table
[docs] def _add_horizontal_lines(self) -> Table: """Adds the horizontal lines to the table.""" anchor_left = self.get_left()[0] - 0.5 * self.h_buff anchor_right = self.get_right()[0] + 0.5 * self.h_buff line_group = VGroup() if self.include_outer_lines: anchor = self.get_rows()[0].get_top()[1] + 0.5 * self.v_buff line = Line( [anchor_left, anchor, 0], [anchor_right, anchor, 0], **self.line_config ) line_group.add(line) self.add(line) anchor = self.get_rows()[-1].get_bottom()[1] - 0.5 * self.v_buff line = Line( [anchor_left, anchor, 0], [anchor_right, anchor, 0], **self.line_config ) line_group.add(line) self.add(line) for k in range(len(self.mob_table) - 1): anchor = self.get_rows()[k + 1].get_top()[1] + 0.5 * ( self.get_rows()[k].get_bottom()[1] - self.get_rows()[k + 1].get_top()[1] ) line = Line( [anchor_left, anchor, 0], [anchor_right, anchor, 0], **self.line_config ) line_group.add(line) self.add(line) self.horizontal_lines = line_group return self
[docs] def _add_vertical_lines(self) -> Table: """Adds the vertical lines to the table""" anchor_top = self.get_rows().get_top()[1] + 0.5 * self.v_buff anchor_bottom = self.get_rows().get_bottom()[1] - 0.5 * self.v_buff line_group = VGroup() if self.include_outer_lines: anchor = self.get_columns()[0].get_left()[0] - 0.5 * self.h_buff line = Line( [anchor, anchor_top, 0], [anchor, anchor_bottom, 0], **self.line_config ) line_group.add(line) self.add(line) anchor = self.get_columns()[-1].get_right()[0] + 0.5 * self.h_buff line = Line( [anchor, anchor_top, 0], [anchor, anchor_bottom, 0], **self.line_config ) line_group.add(line) self.add(line) for k in range(len(self.mob_table[0]) - 1): anchor = self.get_columns()[k + 1].get_left()[0] + 0.5 * ( self.get_columns()[k].get_right()[0] - self.get_columns()[k + 1].get_left()[0] ) line = Line( [anchor, anchor_bottom, 0], [anchor, anchor_top, 0], **self.line_config ) line_group.add(line) self.add(line) self.vertical_lines = line_group return self
[docs] def get_horizontal_lines(self) -> VGroup: """Return the horizontal lines of the table. Returns -------- :class:`~.VGroup` :class:`~.VGroup` containing all the horizontal lines of the table. Examples -------- .. manim:: GetHorizontalLinesExample :save_last_frame: class GetHorizontalLinesExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) table.get_horizontal_lines().set_color(RED) self.add(table) """ return self.horizontal_lines
[docs] def get_vertical_lines(self) -> VGroup: """Return the vertical lines of the table. Returns -------- :class:`~.VGroup` :class:`~.VGroup` containing all the vertical lines of the table. Examples -------- .. manim:: GetVerticalLinesExample :save_last_frame: class GetVerticalLinesExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) table.get_vertical_lines()[0].set_color(RED) self.add(table) """ return self.vertical_lines
[docs] def get_columns(self) -> VGroup: """Return columns of the table as a :class:`~.VGroup` of :class:`~.VGroup`. Returns -------- :class:`~.VGroup` :class:`~.VGroup` containing each column in a :class:`~.VGroup`. Examples -------- .. manim:: GetColumnsExample :save_last_frame: class GetColumnsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) table.add(SurroundingRectangle(table.get_columns()[1])) self.add(table) """ return VGroup( *( VGroup(*(row[i] for row in self.mob_table)) for i in range(len(self.mob_table[0])) ) )
[docs] def get_rows(self) -> VGroup: """Return the rows of the table as a :class:`~.VGroup` of :class:`~.VGroup`. Returns -------- :class:`~.VGroup` :class:`~.VGroup` containing each row in a :class:`~.VGroup`. Examples -------- .. manim:: GetRowsExample :save_last_frame: class GetRowsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) table.add(SurroundingRectangle(table.get_rows()[1])) self.add(table) """ return VGroup(*(VGroup(*row) for row in self.mob_table))
[docs] def set_column_colors(self, *colors: Iterable[ParsableManimColor]) -> Table: """Set individual colors for each column of the table. Parameters ---------- colors An iterable of colors; each color corresponds to a column. Examples -------- .. manim:: SetColumnColorsExample :save_last_frame: class SetColumnColorsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")] ).set_column_colors([RED,BLUE], GREEN) self.add(table) """ columns = self.get_columns() for color, column in zip(colors, columns): column.set_color(color) return self
[docs] def set_row_colors(self, *colors: Iterable[ParsableManimColor]) -> Table: """Set individual colors for each row of the table. Parameters ---------- colors An iterable of colors; each color corresponds to a row. Examples -------- .. manim:: SetRowColorsExample :save_last_frame: class SetRowColorsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")] ).set_row_colors([RED,BLUE], GREEN) self.add(table) """ rows = self.get_rows() for color, row in zip(colors, rows): row.set_color(color) return self
[docs] def get_entries( self, pos: Sequence[int] | None = None, ) -> VMobject | VGroup: """Return the individual entries of the table (including labels) or one specific entry if the parameter, ``pos``, is set. Parameters ---------- pos The position of a specific entry on the table. ``(1,1)`` being the top left entry of the table. Returns ------- Union[:class:`~.VMobject`, :class:`~.VGroup`] :class:`~.VGroup` containing all entries of the table (including labels) or the :class:`~.VMobject` at the given position if ``pos`` is set. Examples -------- .. manim:: GetEntriesExample :save_last_frame: class GetEntriesExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) ent = table.get_entries() for item in ent: item.set_color(random_bright_color()) table.get_entries((2,2)).rotate(PI) self.add(table) """ if pos is not None: if ( self.row_labels is not None and self.col_labels is not None and self.top_left_entry is None ): index = len(self.mob_table[0]) * (pos[0] - 1) + pos[1] - 2 return self.elements[index] else: index = len(self.mob_table[0]) * (pos[0] - 1) + pos[1] - 1 return self.elements[index] else: return self.elements
[docs] def get_entries_without_labels( self, pos: Sequence[int] | None = None, ) -> VMobject | VGroup: """Return the individual entries of the table (without labels) or one specific entry if the parameter, ``pos``, is set. Parameters ---------- pos The position of a specific entry on the table. ``(1,1)`` being the top left entry of the table (without labels). Returns ------- Union[:class:`~.VMobject`, :class:`~.VGroup`] :class:`~.VGroup` containing all entries of the table (without labels) or the :class:`~.VMobject` at the given position if ``pos`` is set. Examples -------- .. manim:: GetEntriesWithoutLabelsExample :save_last_frame: class GetEntriesWithoutLabelsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) ent = table.get_entries_without_labels() colors = [BLUE, GREEN, YELLOW, RED] for k in range(len(colors)): ent[k].set_color(colors[k]) table.get_entries_without_labels((2,2)).rotate(PI) self.add(table) """ if pos is not None: index = self.col_dim * (pos[0] - 1) + pos[1] - 1 return self.elements_without_labels[index] else: return self.elements_without_labels
[docs] def get_row_labels(self) -> VGroup: """Return the row labels of the table. Returns ------- :class:`~.VGroup` :class:`~.VGroup` containing the row labels of the table. Examples -------- .. manim:: GetRowLabelsExample :save_last_frame: class GetRowLabelsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) lab = table.get_row_labels() for item in lab: item.set_color(random_bright_color()) self.add(table) """ return VGroup(*self.row_labels)
[docs] def get_col_labels(self) -> VGroup: """Return the column labels of the table. Returns -------- :class:`~.VGroup` VGroup containing the column labels of the table. Examples -------- .. manim:: GetColLabelsExample :save_last_frame: class GetColLabelsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) lab = table.get_col_labels() for item in lab: item.set_color(random_bright_color()) self.add(table) """ return VGroup(*self.col_labels)
[docs] def get_labels(self) -> VGroup: """Returns the labels of the table. Returns -------- :class:`~.VGroup` :class:`~.VGroup` containing all the labels of the table. Examples -------- .. manim:: GetLabelsExample :save_last_frame: class GetLabelsExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) lab = table.get_labels() colors = [BLUE, GREEN, YELLOW, RED] for k in range(len(colors)): lab[k].set_color(colors[k]) self.add(table) """ label_group = VGroup() if self.top_left_entry is not None: label_group.add(self.top_left_entry) for label in (self.col_labels, self.row_labels): if label is not None: label_group.add(*label) return label_group
[docs] def add_background_to_entries(self, color: ParsableManimColor = BLACK) -> Table: """Adds a black :class:`~.BackgroundRectangle` to each entry of the table.""" for mob in self.get_entries(): mob.add_background_rectangle(color=ManimColor(color)) return self
[docs] def get_cell(self, pos: Sequence[int] = (1, 1), **kwargs) -> Polygon: """Returns one specific cell as a rectangular :class:`~.Polygon` without the entry. Parameters ---------- pos The position of a specific entry on the table. ``(1,1)`` being the top left entry of the table. kwargs Additional arguments to be passed to :class:`~.Polygon`. Returns ------- :class:`~.Polygon` Polygon mimicking one specific cell of the Table. Examples -------- .. manim:: GetCellExample :save_last_frame: class GetCellExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) cell = table.get_cell((2,2), color=RED) self.add(table, cell) """ row = self.get_rows()[pos[0] - 1] col = self.get_columns()[pos[1] - 1] edge_UL = [ col.get_left()[0] - self.h_buff / 2, row.get_top()[1] + self.v_buff / 2, 0, ] edge_UR = [ col.get_right()[0] + self.h_buff / 2, row.get_top()[1] + self.v_buff / 2, 0, ] edge_DL = [ col.get_left()[0] - self.h_buff / 2, row.get_bottom()[1] - self.v_buff / 2, 0, ] edge_DR = [ col.get_right()[0] + self.h_buff / 2, row.get_bottom()[1] - self.v_buff / 2, 0, ] rec = Polygon(edge_UL, edge_UR, edge_DR, edge_DL, **kwargs) return rec
[docs] def get_highlighted_cell( self, pos: Sequence[int] = (1, 1), color: ParsableManimColor = YELLOW, **kwargs ) -> BackgroundRectangle: """Returns a :class:`~.BackgroundRectangle` of the cell at the given position. Parameters ---------- pos The position of a specific entry on the table. ``(1,1)`` being the top left entry of the table. color The color used to highlight the cell. kwargs Additional arguments to be passed to :class:`~.BackgroundRectangle`. Examples -------- .. manim:: GetHighlightedCellExample :save_last_frame: class GetHighlightedCellExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) highlight = table.get_highlighted_cell((2,2), color=GREEN) table.add_to_back(highlight) self.add(table) """ cell = self.get_cell(pos) bg_cell = BackgroundRectangle(cell, color=ManimColor(color), **kwargs) return bg_cell
[docs] def add_highlighted_cell( self, pos: Sequence[int] = (1, 1), color: ParsableManimColor = YELLOW, **kwargs ) -> Table: """Highlights one cell at a specific position on the table by adding a :class:`~.BackgroundRectangle`. Parameters ---------- pos The position of a specific entry on the table. ``(1,1)`` being the top left entry of the table. color The color used to highlight the cell. kwargs Additional arguments to be passed to :class:`~.BackgroundRectangle`. Examples -------- .. manim:: AddHighlightedCellExample :save_last_frame: class AddHighlightedCellExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")]) table.add_highlighted_cell((2,2), color=GREEN) self.add(table) """ bg_cell = self.get_highlighted_cell(pos, color=ManimColor(color), **kwargs) self.add_to_back(bg_cell) entry = self.get_entries(pos) entry.background_rectangle = bg_cell return self
[docs] def create( self, lag_ratio: float = 1, line_animation: Callable[[VMobject | VGroup], Animation] = Create, label_animation: Callable[[VMobject | VGroup], Animation] = Write, element_animation: Callable[[VMobject | VGroup], Animation] = Create, entry_animation: Callable[[VMobject | VGroup], Animation] = FadeIn, **kwargs, ) -> AnimationGroup: """Customized create-type function for tables. Parameters ---------- lag_ratio The lag ratio of the animation. line_animation The animation style of the table lines, see :mod:`~.creation` for examples. label_animation The animation style of the table labels, see :mod:`~.creation` for examples. element_animation The animation style of the table elements, see :mod:`~.creation` for examples. entry_animation The entry animation of the table background, see :mod:`~.creation` for examples. kwargs Further arguments passed to the creation animations. Returns ------- :class:`~.AnimationGroup` AnimationGroup containing creation of the lines and of the elements. Examples -------- .. manim:: CreateTableExample class CreateTableExample(Scene): def construct(self): table = Table( [["First", "Second"], ["Third","Fourth"]], row_labels=[Text("R1"), Text("R2")], col_labels=[Text("C1"), Text("C2")], include_outer_lines=True) self.play(table.create()) self.wait() """ animations: Sequence[Animation] = [ line_animation( VGroup(self.vertical_lines, self.horizontal_lines), **kwargs, ), element_animation(self.elements_without_labels.set_z_index(2), **kwargs), ] if self.get_labels(): animations += [ label_animation(self.get_labels(), **kwargs), ] if self.get_entries(): for entry in self.elements_without_labels: try: animations += [ entry_animation( entry.background_rectangle, **kwargs, ) ] except AttributeError: continue return AnimationGroup(*animations, lag_ratio=lag_ratio)
[docs] def scale(self, scale_factor: float, **kwargs): # h_buff and v_buff must be adjusted so that Table.get_cell # can construct an accurate polygon for a cell. self.h_buff *= scale_factor self.v_buff *= scale_factor super().scale(scale_factor, **kwargs) return self
[docs]class MathTable(Table): """A specialized :class:`~.Table` mobject for use with LaTeX. Examples -------- .. manim:: MathTableExample :save_last_frame: class MathTableExample(Scene): def construct(self): t0 = MathTable( [["+", 0, 5, 10], [0, 0, 5, 10], [2, 2, 7, 12], [4, 4, 9, 14]], include_outer_lines=True) self.add(t0) """ def __init__( self, table: Iterable[Iterable[float | str]], element_to_mobject: Callable[[float | str], VMobject] = MathTex, **kwargs, ): """ Special case of :class:`~.Table` with `element_to_mobject` set to :class:`~.MathTex`. Every entry in `table` is set in a Latex `align` environment. Parameters ---------- table A 2d array or list of lists. Content of the table have to be valid input for :class:`~.MathTex`. element_to_mobject The :class:`~.Mobject` class applied to the table entries. Set as :class:`~.MathTex`. kwargs Additional arguments to be passed to :class:`~.Table`. """ super().__init__( table, element_to_mobject=element_to_mobject, **kwargs, )
[docs]class MobjectTable(Table): """A specialized :class:`~.Table` mobject for use with :class:`~.Mobject`. Examples -------- .. manim:: MobjectTableExample :save_last_frame: class MobjectTableExample(Scene): def construct(self): cross = VGroup( Line(UP + LEFT, DOWN + RIGHT), Line(UP + RIGHT, DOWN + LEFT), ) a = Circle().set_color(RED).scale(0.5) b = cross.set_color(BLUE).scale(0.5) t0 = MobjectTable( [[a.copy(),b.copy(),a.copy()], [b.copy(),a.copy(),a.copy()], [a.copy(),b.copy(),b.copy()]] ) line = Line( t0.get_corner(DL), t0.get_corner(UR) ).set_color(RED) self.add(t0, line) """ def __init__( self, table: Iterable[Iterable[VMobject]], element_to_mobject: Callable[[VMobject], VMobject] = lambda m: m, **kwargs, ): """ Special case of :class:`~.Table` with ``element_to_mobject`` set to an identity function. Here, every item in ``table`` must already be of type :class:`~.Mobject`. Parameters ---------- table A 2D array or list of lists. Content of the table must be of type :class:`~.Mobject`. element_to_mobject The :class:`~.Mobject` class applied to the table entries. Set as ``lambda m : m`` to return itself. kwargs Additional arguments to be passed to :class:`~.Table`. """ super().__init__(table, element_to_mobject=element_to_mobject, **kwargs)
[docs]class IntegerTable(Table): """A specialized :class:`~.Table` mobject for use with :class:`~.Integer`. Examples -------- .. manim:: IntegerTableExample :save_last_frame: class IntegerTableExample(Scene): def construct(self): t0 = IntegerTable( [[0,30,45,60,90], [90,60,45,30,0]], col_labels=[ MathTex("\\\\frac{\\sqrt{0}}{2}"), MathTex("\\\\frac{\\sqrt{1}}{2}"), MathTex("\\\\frac{\\sqrt{2}}{2}"), MathTex("\\\\frac{\\sqrt{3}}{2}"), MathTex("\\\\frac{\\sqrt{4}}{2}")], row_labels=[MathTex("\\sin"), MathTex("\\cos")], h_buff=1, element_to_mobject_config={"unit": "^{\\circ}"}) self.add(t0) """ def __init__( self, table: Iterable[Iterable[float | str]], element_to_mobject: Callable[[float | str], VMobject] = Integer, **kwargs, ): """ Special case of :class:`~.Table` with `element_to_mobject` set to :class:`~.Integer`. Will round if there are decimal entries in the table. Parameters ---------- table A 2d array or list of lists. Content of the table has to be valid input for :class:`~.Integer`. element_to_mobject The :class:`~.Mobject` class applied to the table entries. Set as :class:`~.Integer`. kwargs Additional arguments to be passed to :class:`~.Table`. """ super().__init__(table, element_to_mobject=element_to_mobject, **kwargs)
[docs]class DecimalTable(Table): """A specialized :class:`~.Table` mobject for use with :class:`~.DecimalNumber` to display decimal entries. Examples -------- .. manim:: DecimalTableExample :save_last_frame: class DecimalTableExample(Scene): def construct(self): x_vals = [-2,-1,0,1,2] y_vals = np.exp(x_vals) t0 = DecimalTable( [x_vals, y_vals], row_labels=[MathTex("x"), MathTex("f(x)=e^{x}")], h_buff=1, element_to_mobject_config={"num_decimal_places": 2}) self.add(t0) """ def __init__( self, table: Iterable[Iterable[float | str]], element_to_mobject: Callable[[float | str], VMobject] = DecimalNumber, element_to_mobject_config: dict = {"num_decimal_places": 1}, **kwargs, ): """ Special case of :class:`~.Table` with ``element_to_mobject`` set to :class:`~.DecimalNumber`. By default, ``num_decimal_places`` is set to 1. Will round/truncate the decimal places based on the provided ``element_to_mobject_config``. Parameters ---------- table A 2D array, or a list of lists. Content of the table must be valid input for :class:`~.DecimalNumber`. element_to_mobject The :class:`~.Mobject` class applied to the table entries. Set as :class:`~.DecimalNumber`. element_to_mobject_config Element to mobject config, here set as {"num_decimal_places": 1}. kwargs Additional arguments to be passed to :class:`~.Table`. """ super().__init__( table, element_to_mobject=element_to_mobject, element_to_mobject_config=element_to_mobject_config, **kwargs, )