def overview(scene): title = Text( """ Manim is a Python library used to generate videos, and Code Video Generator extends it to make it easy to generate code-related videos ... in fact, it is what was used to generate this video! """, font="Helvetica", line_spacing=0.5, ).scale(0.7) scene.play(Create(title, run_time=10, rate_func=linear)) scene.wait(3) sub = (Text( """ Here is an example: """, font="Helvetica", ).scale(0.7).next_to(title, direction=DOWN, buff=MED_LARGE_BUFF, aligned_edge=LEFT)) scene.play(Create(sub)) scene.wait(2) scene.clear()
def __init__(self, commons_left=SVGS.DNA, commons_right=None, **kwargs): super().__init__(**kwargs) # Logo level lol = Text('Language of Life') lol[1].set_color(BLUE) if is_manimce(self): # Beware: currently semantics seem to have changed in manim ce and this should be 11 # are they not counting spaces? lol[11].set_color(GREEN) else: lol[13].set_color(GREEN) commons = Text('commons') commons.next_to(lol, DOWN) self.lol = lol self.commons = commons self.add( self.lol, self.commons, ) self.commons_left = self.commons_right = None self._set_left_right(commons_left, commons_right)
def construct(self): # Atom level adenine = Text(ADENINE_SMILES) # Nucleotide level dna = Text('ACTGAATATAGACTATA', t2c={ 'A': RED, 'C': BLUE, 'T': GREEN, 'G': PURPLE }) # Amino acid level aas = 'VQGGAAVQQEVLA' aas = Text(aas, t2c=get_aa_hex_color_dict('skylign_protein')) # Logo level logo = LoLLogo() # Animate... from nucleotide to LoL Commons self.wait() self.play(Write(adenine)) self.wait() if self.add_vector_transform: # FIXME: This is not quite pretty / useful at the moment numbers = Text( '[0.12 0.32 0.01 0.88 0.99 0.22 0.55 0.42 0.13 0.07]') replacements = [adenine, dna, aas, numbers, logo.lol] else: replacements = [adenine, dna, aas, logo.lol] for source, target in zip(replacements, replacements[1:]): self.play(ReplacementTransform(source, target)) self.wait() self.play(Write(logo.commons), FadeIn(logo.commons_left), FadeIn(logo.commons_right)) self.wait() for replacer in self.replacers: logo.replace_left_right(self, replacer, run_time_s=0.8) self.wait(0.3) # Move logo to left lower corner if self.logo_down: mini_logo = logo.copy() mini_logo.scale(0.5) mini_logo.to_corner() self.play(Transform(logo, mini_logo)) # And keep the scene # self.play(Write(Text('Corporate info follows...'))) self.wait(5)
def title_scene(scene): scene.add_background(f"{example_dir}/resources/blackboard.jpg") title = Text("How to use Code Video Generator", font="Helvetica") scene.play(Create(title)) scene.play( FadeIn( Text(f"Code and examples from version {__version__}", font="Helvetica").scale(0.6).next_to(title, direction=DOWN, buff=LARGE_BUFF))) scene.wait(3) scene.clear()
def get_node(self, value) -> VDict: node = VDict({ 'node': Circle(radius=self.radius), 'label': Text(value) }) node['label'].scale(self.font_scale) return node
def connect(self, source: Mobject, target: Mobject, label: Optional[str] = None) -> Connection: result = Connection() label_direction = UP label_buff = 0 arrow: Optional[Arrow] = None if source.get_x(RIGHT) <= target.get_x(LEFT): arrow = Arrow(start=source.get_edge_center(RIGHT), end=target.get_edge_center(LEFT), buff=0) label_direction = UP elif source.get_x(LEFT) >= target.get_x(RIGHT): arrow = Arrow(start=source.get_edge_center(LEFT), end=target.get_edge_center(RIGHT), buff=0) label_direction = UP elif source.get_y(DOWN) >= target.get_y(UP): arrow = Arrow(start=source.get_edge_center(DOWN), end=target.get_edge_center(UP), buff=0) label_direction = RIGHT label_buff = VERTICAL_ARROW_LABEL_BUFF elif source.get_y(UP) <= target.get_y(DOWN): arrow = Arrow(start=source.get_edge_center(UP), end=target.get_edge_center(DOWN), buff=0) label_direction = RIGHT label_buff = VERTICAL_ARROW_LABEL_BUFF if not arrow: raise ValueError("Unable to connect") result.add(arrow) if label: text = Text(label, font=self.text_font, size=0.7, slant=ITALIC) text.next_to(arrow, direction=label_direction, buff=label_buff) result.add(text) return result
def _box( self, text, border_builder: Callable[[Text], Polygon], ): if self.wrap_at: text = "\n".join(wrap(text, self.wrap_at)) title = Text(text, **self.text_attrs) border = border_builder(title) border.set_color(self.border_color) bg_color, bg_opacity = self._color_and_opacity(self.bg_color, text) border.set_fill(color=bg_color, opacity=bg_opacity) if self.rounded: border.round_corners(ROUNDED_RADIUS) title.move_to(border) self.add(border, title) if self.shadow and bg_opacity: s_rect = border.copy() s_rect.set_color(SHADOW_COLOR) shadow_opacity = SHADOW_OPACITY s_rect.set_stroke(width=0) s_rect.set_background_stroke(width=0) s_rect.set_fill(opacity=shadow_opacity) s_rect.scale(1 + SHADOW_SHIFT) s_rect.shift(SHADOW_SHIFT * DR) self.add_to_back(s_rect)
def __init__(self, diagram: SequenceDiagram, title: str): super().__init__() self.diagram = diagram self.title = title tblock = VGroup() title = Text(title, font=self.CONFIG["text_font"], color=self.CONFIG["actor_text_color"]) rect = (Rectangle(height=self._get_text_height(title) + 0.5, width=title.get_width() + 0.5).round_corners(0.2).set_fill( self.CONFIG["actor_fill_color"], 1)) title.move_to(rect) tblock.add(rect, title) self.block = tblock self.line = DashedLine( start=rect.get_edge_center(DOWN), end=[rect.get_center()[0], rect.get_bottom()[1], 0], stroke_style="dashed", dash_length=DEFAULT_DASH_LENGTH * 4, stroke_width=DEFAULT_STROKE_WIDTH / 2, positive_space_ratio=0.7, ) self.bblock = tblock.copy() self.bblock.next_to(self.line, direction=DOWN, buff=0) self.add(tblock, self.line, self.bblock)
def demo_boxes(scene: CodeScene): scene.add_background(f"{example_dir}/resources/blackboard.jpg") title = Text("examples/boxes.py", font=DEFAULT_FONT) title.to_edge(UP) scene.add(title) comp1 = TextBox("Component A", shadow=False) comp2 = TextBox("Component B", shadow=False) comp3 = TextBox("Component C", shadow=False) comp1.next_to(title, DOWN, buff=2) comp1.to_edge(LEFT) comp2.next_to(comp1, DOWN, buff=1) comp3.next_to(comp1, RIGHT, buff=4) arrow1 = Connection(comp2, comp1, "Do something") arrow2 = Connection(comp1, comp3, "Do another thing") scene.play(FadeIn(comp2)) scene.wait_until_beat(1) scene.play(Create(arrow1)) scene.play(FadeIn(comp1)) scene.wait_until_beat(1) scene.play(Create(arrow2)) scene.play(FadeIn(comp3)) scene.wait_until_beat(4) scene.clear()
def test_whether_svg_file_created() -> None: """Checks Whether SVG file is created in desired location""" temp_pango_text = Text("hello", size=1) theo_path = os.path.abspath( os.path.join(folder, temp_pango_text.text2hash() + ".svg")) actual_path = os.path.abspath(temp_pango_text.text2svg()) assert theo_path == actual_path
def construct(self): rng = np.random.RandomState(self.seed) moleculizer = partial( new_molecule, colors=lambda: rng.choice(MOLECULE_COLORS, size=3, replace=True)) proteins = molecule_universe_grid( moleculizer, num_molecules=(5, 8)).scale(0.3).center() proteins_frame = SurroundingRectangle(proteins, color=WHITE).round_corners(0.5) universe_title = Text('Known proteins').scale(0.7).next_to( proteins_frame, UP) framed_proteins = VGroup(universe_title, proteins_frame, proteins).to_edge(LEFT) self.play(FadeIn(framed_proteins)) self.wait(3) # --- Sequence -> Number -> MLM heavy, hcdr3 = hiv_antibody() heavy.next_to(framed_proteins, RIGHT) self.play(Transform(proteins[23], heavy)) self.wait(5) mlm = MLM().next_to(framed_proteins, RIGHT) self.play(ShrinkToCenter(heavy)) # , mlm.text self.wait(5) # FIXME: just to break here if mlm.text is not None: return # --- Subsets selected_proteins = [ proteins[i].copy() for i in rng.choice( len(proteins), replace=False, size=len(proteins) // 3) ] antibodies = VGroup( * [molecule_from_molecule(protein) for protein in selected_proteins]) antibodies_frame = (SurroundingRectangle(antibodies).match_color( proteins_frame).match_width(proteins_frame).match_height( proteins_frame)).round_corners(0.5) framed_antibodies = VGroup(antibodies_frame, antibodies) framed_antibodies.next_to(proteins, RIGHT, buff=MED_LARGE_BUFF) self.play( *[ ReplacementTransform(protein, antibody) for protein, antibody in zip(selected_proteins, antibodies) ], Write(antibodies_frame)) self.wait(4)
def test_graph_add_vertices(): G = Graph([1, 2, 3], [(1, 2), (2, 3)]) G.add_vertices(4) assert str(G) == "Graph on 4 vertices and 2 edges" G.add_vertices(5, labels={5: Text("5")}) assert str(G) == "Graph on 5 vertices and 2 edges" assert 5 in G._labels assert 5 in G._vertex_config G.add_vertices(6, 7, 8) assert len(G.vertices) == 8 assert len(G._graph.nodes()) == 8
def finish(self, target: Actor): self.target = target line = Arrow(start=[self.source.get_center()[0], 0, 0], end=[self.target.get_center()[0], 0, 0], buff=0) self.add(line) text = Text(self.label, font=self.source.CONFIG["text_font"]).scale(0.7).next_to( line, direction=UP, buff=0) self.add(text)
def demo_sequence(scene: CodeScene): title = Text( """ You can use Code Video Generator to also illustrate high-level concepts through sequence diagrams, or if you want more control, your own block diagrams: """, font=DEFAULT_FONT, line_spacing=0.5, ).scale(0.7) scene.play(Create(title, run_time=4, rate_func=linear)) scene.wait(3) scene.clear() scene.add_background(f"{example_dir}/resources/blackboard.jpg") title = Text("examples/sequence-diagrams.py", font=DEFAULT_FONT) title.to_edge(UP) scene.add(title) diagram = AutoScaled(SequenceDiagram()) browser, web, app = diagram.add_objects("Browser", "Web", "App") browser.to(web, "Make a request") web.to(app, "Request with no response") web.to(app, "Retrieve a json object") app.to(app, "Calls itself") app.note("Do lots and lots and lots of thinking") app.to(web, "Value from db") web.to(browser, "HTML response") diagram.next_to(title, DOWN) scene.play(Create(diagram)) for interaction in diagram.get_interactions(): scene.play(Create(interaction)) scene.wait(3) scene.play(FadeOut(diagram), *[FadeOut(item) for item in diagram.interactions]) scene.clear()
def test_graph_add_vertices(using_opengl_renderer): G = Graph([1, 2, 3], [(1, 2), (2, 3)]) G.add_vertices(4) assert len(G.vertices) == 4 assert len(G.edges) == 2 G.add_vertices(5, labels={5: Text("5")}) assert len(G.vertices) == 5 assert len(G.edges) == 2 assert 5 in G._labels assert 5 in G._vertex_config G.add_vertices(6, 7, 8) assert len(G.vertices) == 8 assert len(G._graph.nodes()) == 8
def animate_code_comments( self, path: str, title: str = None, keep_comments: bool = False, start_line: int = 1, end_line: Optional[int] = None, reset_at_end: bool = True, ) -> Code: """ Parses a code file, displays it or a section of it, and animates comments Args: path: The source code file path title: The title or file path if not provided keep_comments: Whether to keep comments or strip them when displaying start_line: The start line number, used for displaying only a partial file end_line: The end line number, defaults to the end of the file reset_at_end: Whether to reset the code to full screen at the end or not """ code, comments = comment_parser.parse(path, keep_comments=keep_comments, start_line=start_line, end_line=end_line) tex = AutoScaled( PartialCode(code=code, start_line=start_line, style=self.code_theme)) if title is None: title = path title = Text(title, color=WHITE).to_edge(edge=UP) self.add(title) tex.next_to(title, DOWN) self.play(ShowCreation(tex)) self.wait() for comment in comments: self.highlight_lines(tex, comment.start, comment.end, comment.caption) if self.caption: self.play(FadeOut(self.caption)) self.caption = None if reset_at_end: self.play(HighlightNone(tex)) self.play(ApplyMethod(tex.full_size)) return tex
def __init__(self, target: Actor, label: str, direction: np.array): super().__init__(target) self.target = target self.label = "\n".join(wrap(label, 30)) self.direction = direction block = VGroup() title = Text(self.label, font="Helvetica").scale(0.7) rect = Rectangle(height=title.get_height() + 0.3, width=title.get_width() + 0.3) title.move_to(rect) block.add(rect, title) block.next_to(target.get_center(), direction) self.add(block)
def __init__(self, source: Mobject, target: Mobject, label: Optional[str] = None, font=DEFAULT_FONT, **kwargs): """ Args: source: The source object target: The target object label: The optional label text to put over the arrow """ super().__init__(**kwargs) self.font = font label_direction = UP label_buff = 0 arrow: Optional[Arrow] = None if source.get_x(RIGHT) <= target.get_x(LEFT): arrow = Arrow(start=source.get_edge_center(RIGHT), end=target.get_edge_center(LEFT), buff=0) label_direction = UP elif source.get_x(LEFT) >= target.get_x(RIGHT): arrow = Arrow(start=source.get_edge_center(LEFT), end=target.get_edge_center(RIGHT), buff=0) label_direction = UP elif source.get_y(DOWN) >= target.get_y(UP): arrow = Arrow(start=source.get_edge_center(DOWN), end=target.get_edge_center(UP), buff=0) label_direction = RIGHT label_buff = VERTICAL_ARROW_LABEL_BUFF elif source.get_y(UP) <= target.get_y(DOWN): arrow = Arrow(start=source.get_edge_center(UP), end=target.get_edge_center(DOWN), buff=0) label_direction = RIGHT label_buff = VERTICAL_ARROW_LABEL_BUFF if not arrow: raise ValueError("Unable to connect") self.add(arrow) if label: text = Text(label, font=self.font, size=0.5, slant=ITALIC) text.next_to(arrow, direction=label_direction, buff=label_buff) self.add(text)
def __init__(self, source: Actor, target: Actor, label: str = "", font=DEFAULT_FONT, **kwargs): super().__init__(source, font=font, **kwargs) self.target = target self.label = label self.font = font line = Arrow( start=[self.source.get_center()[0], 0, 0], end=[self.target.get_center()[0], 0, 0], buff=0, stroke_width=ARROW_STROKE_WIDTH, ) text = Text(self.label, font=self.font, size=0.5, slant=ITALIC) text.next_to(line, direction=UP, buff=0) self.add(line, text)
def goodbye(scene: CodeScene): title = Text( """ Try Code Video Generator today at: https://github.com/sleuth-io/code-video-generator Thanks for watching!""", font="Helvetica", line_spacing=0.5, ).scale(0.7) title.to_edge(LEFT) scene.play(Create(title, run_time=4, rate_func=linear)) scene.wait(5) scene.play(FadeOut(title))
def test_t2s() -> None: size = 1 temp_pango_text = Text("Helloworld", t2s={"world": ITALIC}) surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_markup( 'Hello<span style="italic">world</span>') # yay, pango markup pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def finish(self, target: Actor): self.target = target line = Arrow( start=[self.source.get_center()[0], 0, 0], end=[self.target.get_center()[0], 0, 0], buff=0, stroke_width=ARROW_STROKE_WIDTH, ) text = Text(self.label, font=self.source.diagram.lib.text_font, size=0.7, slant=ITALIC) text.next_to(line, direction=UP, buff=0) self.add(line, text) return self
def test_rtl_text_to_svgobject() -> None: """Checks number of submobjects generated when directly called using ``SVGMobject``""" size = 1 text = RTL_TEXT.replace("\n", "") temp_pango_text = Text(text, size=1) surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_text(text) pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def test_tabs_replace() -> None: """Checks whether are there in end svg image. Pango should handle tabs and line breaks.""" size = 1 temp_pango_text = Text("hello\thi\nf") assert temp_pango_text.text == "hellohif" surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_text("hellohif") pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def test_font_face() -> None: """Checks font face using submobject len""" size = 1 text = RTL_TEXT.replace("\n", "") font_face = "sans" temp_pango_text = Text(text, size=1, font=font_face) surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_family(font_face) fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_text(text) pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def __init__(self, icon=SVGS.ANTIBODY, name='Antibody binding\nprediction', **kwargs): super().__init__(**kwargs) self.icon = icon self.name = name if not isinstance(self.icon, Mobject): self.icon = SVGMobject( self.icon).set_color_by_gradient(BLUE).scale(0.6) if not isinstance(self.name, Mobject): self.name = (VGroup( *(Text(name) for name in self.name.splitlines())).scale(0.5).arrange( DOWN, center=True, buff=SMALL_BUFF)) self.name.next_to(self.icon, DOWN) self.icon_name = VGroup(self.icon, self.name) self.frame = SurroundingRectangle( self.icon_name).round_corners(0.5).set_color(WHITE) self.add(self.frame, self.icon_name)
def __init__(self, target: Actor, label: str): super().__init__(target) self.target = target self.label = "\n".join(wrap(label, 30)) line_block = VGroup() spacing = 0.4 distance = 0.8 line = Polygon( [target.get_center()[0], spacing, 0], [target.get_center()[0] + distance, spacing, 0], [target.get_center()[0] + distance, -1 * spacing, 0], [target.get_center()[0] + distance / 2, -1 * spacing, 0], [target.get_center()[0] + distance, -1 * spacing, 0], [target.get_center()[0] + distance, spacing, 0], [target.get_center()[0], spacing, 0], color=WHITE, ) line.set_stroke(width=ARROW_STROKE_WIDTH) arrow = Arrow( start=[target.get_center()[0] + distance, -1 * spacing, 0], end=[target.get_center()[0], -1 * spacing, 0], buff=0, stroke_width=ARROW_STROKE_WIDTH, ) line_block.add(line, arrow) title = Text(self.label, font="Helvetica", size=0.7, slant=ITALIC) title.next_to(line_block) block = VGroup() block.add(line_block, title) block.next_to(target.get_center(), RIGHT) self.add(block)
def _box( self, parent: VGroup, bg_color, color, rounded, shadow, text, wrap_at, border_color, text_attrs: Optional[dict], border_builder: Callable[[Text], Polygon], ) -> VGroup: if wrap_at: text = "\n".join(wrap(text, wrap_at)) title = Text(text, font=self.text_font, color=color, **(text_attrs if text_attrs else {})) border = border_builder(title) border.set_color(border_color) bg_color, bg_opacity = self._color_and_opacity(bg_color, text) border.set_fill(color=bg_color, opacity=bg_opacity) if rounded: border.round_corners(ROUNDED_RADIUS) title.move_to(border) parent.add(border, title) if shadow and bg_opacity: s_rect = border.copy() s_rect.set_color(SHADOW_COLOR) shadow_opacity = SHADOW_OPACITY s_rect.set_stroke(width=0) s_rect.set_background_stroke(color=GREEN, opacity=shadow_opacity, width=0) s_rect.set_fill(opacity=shadow_opacity) s_rect.scale(1 + SHADOW_SHIFT) s_rect.shift(SHADOW_SHIFT * DR) parent.add_to_back(s_rect) return parent
def construct(self): example_dir = dirname(__file__) self.add_background(f"{example_dir}/resources/blackboard.jpg") diagram = AutoScaled(SequenceDiagram()) browser, web, app = diagram.add_objects("Browser", "Web", "App") browser.to(web, "Make a request") web.to(app, "Do a quick thing") web.to(app, "Retrieve a json object") app.to(app, "Call itself") app.note("Do lots and lots and lots of thinking") app.to(web, "Value from db") web.to(browser, "HTML response") title = Text("Sequence Diagram", font=DEFAULT_FONT, size=0.8) title.to_edge(UP) self.add(title) diagram.next_to(title, DOWN) self.play(ShowCreation(diagram)) for interaction in diagram.get_interactions(): self.play(ShowCreation(interaction)) self.wait(5)
def __init__(self, source: Actor, label: str): super().__init__(source) self.label = "\n".join(wrap(label, 30)) line_block = VGroup() spacing = 0.4 distance = 0.8 center_x = source.get_center()[0] line = Polygon( [center_x, spacing, 0], [center_x + distance, spacing, 0], [center_x + distance, -1 * spacing, 0], [center_x + distance / 2, -1 * spacing, 0], [center_x + distance, -1 * spacing, 0], [center_x + distance, spacing, 0], [center_x, spacing, 0], color=WHITE, ) line.set_stroke(width=ARROW_STROKE_WIDTH) arrow = Arrow( start=[center_x + distance, -1 * spacing, 0], end=[center_x, -1 * spacing, 0], buff=0, stroke_width=ARROW_STROKE_WIDTH, ) line_block.add(line, arrow) title = Text(self.label, font=self.source.font, size=0.5, slant=ITALIC) title.next_to(line_block) block = VGroup() block.add(line_block, title) block.next_to(source.get_center(), RIGHT) self.add(block)