Source code for bigger.mappingclassgroup
""" A module for representing triangulations along with laminations and mapping classes on them. """
from __future__ import annotations
from typing import Any, Callable, Generic, Iterable, Optional
from PIL import Image # type: ignore
import bigger
from .types import Edge, FlatTriangle
from .triangulation import Triangle
def splitter(strn: str) -> Iterable[str]:
"""Break strn into words on .'s except when they are inside braces."""
start = 0
brackets = 0
for index, letter in enumerate(strn):
if letter == "." and brackets == 0:
yield strn[start:index]
start = index + 1
elif letter == "{":
brackets += 1
elif letter == "}":
brackets -= 1
if brackets < 0:
raise ValueError("Mismatched braces")
if brackets:
raise ValueError("Mismatched braces")
yield strn[start:]
def swapcase(strn: str) -> str:
"""Swapcase of strn, except for items that are inside braces."""
output = []
brackets = 0
for letter in strn:
output.append(letter if brackets else letter.swapcase())
if letter == "{":
brackets += 1
elif letter == "}":
brackets -= 1
if brackets < 0:
raise ValueError("Mismatched braces")
if brackets:
raise ValueError("Mismatched braces")
return "".join(output)
[docs]class MappingClassGroup(Generic[Edge]):
"""A :class:`~bigger.triangulation.Triangulation` together with a function which produces mapping classes from names."""
def __init__(
self, triangulation: bigger.Triangulation[Edge], generator: Callable[[str], bigger.Encoding[Edge]], layout: Optional[Callable[[Triangle[Edge]], FlatTriangle]] = None
) -> None:
self.triangulation = triangulation
self.generator = generator
self.layout = layout
def _helper(self, name: str) -> bigger.Encoding[Edge]:
if not name:
return self.triangulation.identity()
try:
return self.generator(name)
except ValueError:
return ~(self.generator(swapcase(name)))
def __call__(self, strn: str) -> bigger.Encoding[Edge]:
return bigger.Encoding([item for name in splitter(strn) for item in self._helper(name).sequence])
[docs] def draw(self, edges: list[Edge], **options: Any) -> Image:
"""Return a PIL image of the triangulation of this MCG around the given edges."""
return bigger.draw(self, edges=edges, **options)