Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor StringMobject and relevant classes #1795

Merged
merged 14 commits into from
May 17, 2022
Merged

Refactor StringMobject and relevant classes #1795

merged 14 commits into from
May 17, 2022

Conversation

YishiMichael
Copy link
Contributor

@YishiMichael YishiMichael commented Apr 23, 2022

Motivation

Refactor StringMobject (renamed from LabelledString), MarkupText, MTex classes.

Proposed changes

  • M manimlib/mobject/svg/labelled_string.py: Unify logic from MarkupText, MTex; remove use_plain_tex attributes; support a much more flexible Selector type; allow passing in substrings whose braces or tags aren't paired; rename some methods.
  • M manimlib/mobject/svg/mtex_mobject.py: Allow passing in a 2-tuple to tex_environment, regarded as a prefix and a suffix respectively; remove use_plain_tex attributes.
  • M manimlib/mobject/svg/text_mobject.py: Parse entities to prevent from cutting halfway; remove use_plain_tex attributes.
  • M manimlib/animation/creation.py
  • M manimlib/animation/transform_matching_parts.py
  • M manimlib/scene/interactive_scene.py: Add from __future__ import annotations.

The method renaming in StringMobject class includes:

get_parts_by_string => select_parts
get_part_by_string => select_part
set_color_by_string => set_parts_color
set_color_by_string_to_color_map => set_parts_color_by_dict

The names of aliases remain unchanged (e.g. MTex.get_parts_by_tex)

The type definition of Selector is given below:

Selector = Union[
    str,  # Match all identical strings
    re.Pattern,  # Match the pattern
    tuple[Union[int, None], Union[int, None]],  # A normal span
    Iterable[Union[  # A collection of the above
        str,
        re.Pattern,
        tuple[Union[int, None], Union[int, None]]
    ]]
]

The StringMobject.select_parts method takes in a selector as an input. The isolate parameter, keys of tex_to_color_map, keys of t2c, etc. are also of type selector. StringMobject.select_parts no longer supports case_sensitive, substring and regex parameters --- only substrings inside spans specified by selectors will be selected.

# Equivalent:
text_ = Text("abc", isolate="ab")
#text_ = Text("abc", isolate=["ab"])
#text_ = Text("abc", isolate=(0, 2))
#text_ = Text("abc", isolate=(None, -1))

# Equivalent:
text = Text("abcBC", isolate=("a", "bc", "BC"))
#text = Text("abcBC", isolate=("a", re.compile("bc", re.I)))
#text = Text("abcBC", isolate=((0, 1), (1, 3), (3, 5)))
#text = Text("abcBC", isolate=((None, 1), (1, 3), (-2, None)))

# Equivalent:
text.select_part("bcBC").set_fill(BLUE)
#text.select_part(("bc", "BC")).set_fill(BLUE)
#text.select_part(re.compile("bc", re.I)).set_fill(BLUE)
#text.select_part((1, None)).set_fill(BLUE)

# Equivalent:
poly = MTex(
    "p(x) = a_0 x^0 + a_1 x^1 + \\cdots + a_{n-1} x^{n-1} + a_n x^n",
    tex_to_color_map={re.compile(r"a_(.+?) x\^\1"): ORANGE}
)
#poly = MTex(
#    "p(x) = a_0 x^0 + a_1 x^1 + \\cdots + a_{n-1} x^{n-1} + a_n x^n",
#    tex_to_color_map={
#        s: ORANGE
#        for s in ["a_0 x^0", "a_1 x^1", "a_{n-1} x^{n-1}", "a_n x^n"]
#    }
#)

self.add(VGroup(text_, text, poly).arrange(DOWN))

StringDemo0

This PR handles imbalanced strings and entity strings, so the following will work:

tex = MTex("\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}", tex_to_color_map={"{b^2-4ac": TEAL})
text = MarkupText("<tt>Hello Markup</tt>!", t2c={re.compile(r"\W+"): RED})
self.add(VGroup(tex, text).arrange(DOWN))

StringDemo1

This PR fixes #1792 by removing line_height from the global attribute dictionary if Pango doesn't support.

@YishiMichael
Copy link
Contributor Author

YishiMichael commented Apr 23, 2022

I notice that after refactoring Mobject.copy method, the TransformMatchingStrings animation becomes really slow, and sometimes a RecursionError is raised. I wonder how this happens, and how to fix it.

Code

kw = {
    "isolate": [
        "=",
        "\\int_{0}^{\\infty} \\mathrm{e}^{- t}",
        "\\mathrm{d} t"
    ],
    "tex_to_color_map": {
        "{z}": YELLOW,
        "\\mathrm{e}": MAROON_A,
        "c_{0}": BLUE,
        "c_{1}": BLUE,
        "c_{2}": BLUE,
        "c_{n}": BLUE,
        "{p}": BLUE_B,
        "P \\left( t \\right)": BLUE
    }
}
explicit_formula = MTex(
    "= \\int_{0}^{\\infty} \\mathrm{e}^{- t}"
    " \\left( c_{0} + c_{1} t + c_{2} t^{2} + \\cdots + c_{n} t^{n} \\right) \\mathrm{d} t",
    **kw
)
expanded_formula = MTex(
    "= \\int_{0}^{\\infty} \\mathrm{e}^{- t} c_{0} \\mathrm{d} t"
    " + \\int_{0}^{\\infty} \\mathrm{e}^{- t} c_{1} t \\mathrm{d} t"
    " + \\int_{0}^{\\infty} \\mathrm{e}^{- t} c_{2} t^{2} \\mathrm{d} t"
    " + \\cdots"
    " + \\int_{0}^{\\infty} \\mathrm{e}^{- t} c_{n} t^{n} \\mathrm{d} t",
    **kw
).shift(DOWN)
self.add(explicit_formula)
self.wait()
self.play(TransformMatchingStrings(explicit_formula, expanded_formula))
self.wait()

RecursionError

@YishiMichael YishiMichael mentioned this pull request Apr 23, 2022
@3b1b
Copy link
Owner

3b1b commented Apr 23, 2022

I'll fix up Mobject.copy to avoid the recursive explosion there—apologies for a hasty push there.

@YishiMichael YishiMichael marked this pull request as draft April 25, 2022 14:11
@YishiMichael YishiMichael changed the title Refactor LabelledString and relevant classes Refactor StringMobject and relevant classes May 6, 2022
@YishiMichael YishiMichael marked this pull request as draft May 9, 2022 14:39
@YishiMichael YishiMichael marked this pull request as ready for review May 9, 2022 15:24
@YishiMichael
Copy link
Contributor Author

I noticed some weird behavior of pango as ligatures kick in. I guess it's something deeply rooted in pango that currently I cannot fix. This shall require a deeper look into pango in the future...

text = MarkupText("fast", t2c={"f": TEAL}, font="Source Han Sans Light")  # works
text = MarkupText("fire", t2c={"f": TEAL}, font="Source Han Sans Light")  # fails
text = MarkupText("<span font_features='liga=0'>fire</span>", t2c={"f": TEAL}, font="Source Han Sans Light")  # works

@YishiMichael
Copy link
Contributor Author

The original svg is used instead of the labelled one, so whitespaces around operators won't be eliminated if isolated. That means, MTex("a\\,=\\,b", isolate="=") can now simply be written as MTex("a=b", isolate="=").

@TonyCrane TonyCrane requested a review from 3b1b May 17, 2022 05:11
@3b1b
Copy link
Owner

3b1b commented May 17, 2022

Thank you, this is definitely an improved structure and syntax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot show text in Ubuntu20.04
3 participants