Skip to content

Core

momapy.core

Core dataclasses for maps, models, and layouts.

Modules:

Name Description
elements

Base element classes for maps.

fonts

Font file lookup using uharfbuzz for metadata reading.

layout

Layout element hierarchy: all visual element classes.

map

Top-level Map class.

mapping

Layout-model mapping classes.

model

Abstract model base class.

Classes:

Name Description
Arc

Base class for arcs.

Direction

Cardinal direction a layout element points to.

DoubleHeadedArc

Base class for double-headed arcs.

GroupLayout

Base class for group layouts.

HAlignment

Horizontal alignment of text or content.

Layout

Class for layouts.

LayoutElement

Abstract base class for layout elements.

LayoutModelMapping

Mapping between model elements and layout elements.

LayoutModelMappingBuilder

Mutable builder for LayoutModelMapping.

Map

Class for maps.

MapElement

Base class for map elements.

Model

Abstract base class for models.

ModelElement

Base class for model elements.

Node

Class for nodes.

Orientation

Orientation along an axis.

Shape

Class for basic shapes.

SingleHeadedArc

Base class for single-headed arcs.

TextLayout

Class for text layouts.

VAlignment

Vertical alignment of text or content.

Arc dataclass

Arc(*, id_: str = make_uuid4_as_str(), layout_elements: tuple[LayoutElement, ...] = tuple(), group_fill: NoneValueType | Color | None = None, group_fill_rule: FillRule | None = None, group_filter: NoneValueType | Filter | None = None, group_font_family: str | None = None, group_font_size: float | None = None, group_font_style: FontStyle | None = None, group_font_weight: FontWeight | float | None = None, group_stroke: NoneValueType | Color | None = None, group_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, group_stroke_dashoffset: NoneValueType | float | None = None, group_stroke_width: NoneValueType | float | None = None, group_text_anchor: TextAnchor | None = None, group_transform: NoneValueType | tuple[Transformation, ...] | None = None, end_shorten: float = 0.0, fill: NoneValueType | Color | None = None, filter_: NoneValueType | Filter | None = None, path_fill: NoneValueType | Color | None = None, path_filter: NoneValueType | Filter | None = None, path_stroke: NoneValueType | Color | None = None, path_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, path_stroke_dashoffset: NoneValueType | float | None = None, path_stroke_width: float | None = None, path_transform: NoneValueType | tuple[Transformation, ...] | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, segments: tuple[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc, ...] = tuple(), source: LayoutElement | None = None, start_shorten: float = 0.0, target: LayoutElement | None = None, transform: NoneValueType | tuple[Transformation, ...] | None = None)

Bases: GroupLayout

Base class for arcs.

An arc is a group layout drawn as a path connecting a source to a target, with its own path styling.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'ed420953-849b-4088-99c2-97dc67536c68'
layout_elements tuple[LayoutElement, ...]

The sub-layout elements of the group layout. These are part of the children of the group layout

<dynamic>
group_fill NoneValueType | Color | None

The fill color of the group layout

None
group_fill_rule FillRule | None

The fill rule of the group layout

None
group_filter NoneValueType | Filter | None

The filter of the group layout

None
group_font_family str | None

The font family of the group layout

None
group_font_size float | None

The font size of the group layout

None
group_font_style FontStyle | None

The font style of the group layout

None
group_font_weight FontWeight | float | None

The font weight of the group layout

None
group_stroke NoneValueType | Color | None

The stroke color of the group layout

None
group_stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the group layout

None
group_stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the group layout

None
group_stroke_width NoneValueType | float | None

The stroke width of the group layout

None
group_text_anchor TextAnchor | None

The text anchor of the group layout

None
group_transform NoneValueType | tuple[Transformation, ...] | None

The transform of the group layout

None
end_shorten float

The length the end of the arc will be shorten by

0.0
fill NoneValueType | Color | None

The fill color of the arc

None
filter_ NoneValueType | Filter | None

The filter of the arc

None
path_fill NoneValueType | Color | None

The path fill color of the arc

None
path_filter NoneValueType | Filter | None

The path filter of the arc

None
path_stroke NoneValueType | Color | None

The path stroke color of the arc

None
path_stroke_dasharray NoneValueType | tuple[float, ...] | None

The path stroke dasharray of the arc

None
path_stroke_dashoffset NoneValueType | float | None

The path stroke dashoffset of the arc

None
path_stroke_width float | None

The path stroke width of the arc

None
path_transform NoneValueType | tuple[Transformation, ...] | None

The path transform of the arc

None
stroke NoneValueType | Color | None

The stroke color of the arc

None
stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the arc

None
stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the arc

None
stroke_width NoneValueType | float | None

The stroke width of the arc

None
segments tuple[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc, ...]

The path segments of the arc

<dynamic>
source LayoutElement | None

The source of the arc

None
start_shorten float

The length the start of the arc will be shorten by

0.0
target LayoutElement | None

The target of the arc

None
transform NoneValueType | tuple[Transformation, ...] | None

The transform of the arc

None

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

bbox

Compute and return the bounding box of the group layout element.

childless

Return a copy of the arc with no children.

children

Return the children of the group layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the group layout.

end_point

Return the ending point of the arc.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

fraction

Return the position and angle on the arc at a given fraction (of the total arc length).

length

Return the total length of the arc path.

own_bbox

Compute and return the bounding box of the self drawing element of the group layout.

own_children

Return the self children of the arc.

own_drawing_elements

Return the self drawing elements of the group layout.

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

points

Return the points of the arc path.

start_point

Return the starting point of the arc.

to_geometry

Return a list of geometry primitives from the drawing elements.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

bbox

bbox() -> Bbox

Compute and return the bounding box of the group layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the group layout element."""
    own_bbox = self.own_bbox()
    bboxes = [child.bbox() for child in self.children()]
    min_x = own_bbox.north_west().x
    min_y = own_bbox.north_west().y
    max_x = own_bbox.south_east().x
    max_y = own_bbox.south_east().y
    for bbox in bboxes:
        if bbox.north_west().x < min_x:
            min_x = bbox.north_west().x
        if bbox.north_west().y < min_y:
            min_y = bbox.north_west().y
        if bbox.south_east().x > max_x:
            max_x = bbox.south_east().x
        if bbox.south_east().y > max_y:
            max_y = bbox.south_east().y
    bbox = Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )
    return bbox

childless

childless() -> Self

Return a copy of the arc with no children.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the arc with no children."""
    return dataclasses.replace(self, layout_elements=tuple([]))

children

children() -> list[LayoutElement]

Return the children of the group layout.

These are the self children of the group layout (returned by the own_children method) and the other children of the group layout (given by the layout_elements attribute).

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the group layout.

    These are the self children of the group layout (returned by the `own_children` method) and the other children of the group layout (given by the `layout_elements` attribute).
    """
    return self.own_children() + list(self.layout_elements)

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the group layout.

The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the group layout.

    The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.
    """
    drawing_elements = self.own_drawing_elements()
    for child in self.children():
        if child is not None:
            drawing_elements += child.drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.group_fill,
        fill_rule=self.group_fill_rule,
        filter_=self.group_filter,
        font_family=self.group_font_family,
        font_size=self.group_font_size,
        font_style=self.group_font_style,
        font_weight=self.group_font_weight,
        stroke=self.group_stroke,
        stroke_dasharray=self.group_stroke_dasharray,
        stroke_dashoffset=self.group_stroke_dashoffset,
        stroke_width=self.group_stroke_width,
        text_anchor=self.group_text_anchor,
        transform=self.group_transform,
    )
    return [group]

end_point

end_point() -> Point

Return the ending point of the arc.

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def end_point(self) -> Point:
    """Return the ending point of the arc.

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    return self.points()[-1]

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

fraction

fraction(fraction: float) -> tuple[Point, float]

Return the position and angle on the arc at a given fraction (of the total arc length).

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def fraction(self, fraction: float) -> tuple[Point, float]:
    """Return the position and angle on the arc at a given fraction (of the total arc length).

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    current_length = 0
    length_to_reach = fraction * self.length()
    for segment in self.segments:
        current_length += segment.length()
        if current_length >= length_to_reach:
            break
    segment_start_length = current_length - segment.length()
    segment_fraction = (length_to_reach - segment_start_length) / segment.length()
    position, angle = segment.get_position_and_angle_at_fraction(segment_fraction)
    return position, angle

length

length() -> float

Return the total length of the arc path.

Source code in src/momapy/core/layout.py
def length(self) -> float:
    """Return the total length of the arc path."""
    return sum([segment.length() for segment in self.segments])

own_bbox

own_bbox() -> Bbox

Compute and return the bounding box of the self drawing element of the group layout.

Source code in src/momapy/core/layout.py
def own_bbox(self) -> Bbox:
    """Compute and return the bounding box of the self drawing element of the group layout."""
    primitives = self.own_to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

own_children

own_children() -> list[LayoutElement]

Return the self children of the arc.

Source code in src/momapy/core/layout.py
def own_children(self) -> list[LayoutElement]:
    """Return the self children of the arc."""
    return []

own_drawing_elements abstractmethod

own_drawing_elements() -> list[DrawingElement]

Return the self drawing elements of the group layout.

Source code in src/momapy/core/layout.py
@abc.abstractmethod
def own_drawing_elements(self) -> list[DrawingElement]:
    """Return the self drawing elements of the group layout."""
    pass

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

Source code in src/momapy/core/layout.py
def own_to_geometry(
    self,
) -> list[
    Segment | QuadraticBezierCurve | CubicBezierCurve | GeometryEllipticalArc
]:
    """Return a list of geometry primitives from the self drawing elements."""
    return drawing_elements_to_geometry(self.own_drawing_elements())

points

points() -> list[Point]

Return the points of the arc path.

An arc with no segments has no points and returns an empty list.

Source code in src/momapy/core/layout.py
def points(self) -> list[Point]:
    """Return the points of the arc path.

    An arc with no segments has no points and returns an empty list.
    """
    if not self.segments:
        return []
    points = []
    for segment in self.segments:
        points.append(segment.p1)
    points.append(segment.p2)
    return points

start_point

start_point() -> Point

Return the starting point of the arc.

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def start_point(self) -> Point:
    """Return the starting point of the arc.

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    return self.points()[0]

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

Direction

Bases: Enum

Cardinal direction a layout element points to.

One of the four cardinals (up, right, down, left). For an axis (horizontal or vertical), see Orientation.

DoubleHeadedArc dataclass

DoubleHeadedArc(*, id_: str = make_uuid4_as_str(), layout_elements: tuple[LayoutElement, ...] = tuple(), group_fill: NoneValueType | Color | None = None, group_fill_rule: FillRule | None = None, group_filter: NoneValueType | Filter | None = None, group_font_family: str | None = None, group_font_size: float | None = None, group_font_style: FontStyle | None = None, group_font_weight: FontWeight | float | None = None, group_stroke: NoneValueType | Color | None = None, group_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, group_stroke_dashoffset: NoneValueType | float | None = None, group_stroke_width: NoneValueType | float | None = None, group_text_anchor: TextAnchor | None = None, group_transform: NoneValueType | tuple[Transformation, ...] | None = None, end_shorten: float = 0.0, fill: NoneValueType | Color | None = None, filter_: NoneValueType | Filter | None = None, path_fill: NoneValueType | Color | None = None, path_filter: NoneValueType | Filter | None = None, path_stroke: NoneValueType | Color | None = None, path_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, path_stroke_dashoffset: NoneValueType | float | None = None, path_stroke_width: float | None = None, path_transform: NoneValueType | tuple[Transformation, ...] | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, segments: tuple[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc, ...] = tuple(), source: LayoutElement | None = None, start_shorten: float = 0.0, target: LayoutElement | None = None, transform: NoneValueType | tuple[Transformation, ...] | None = None, end_arrowhead_fill: NoneValueType | Color | None = None, end_arrowhead_filter: NoneValueType | Filter | None = None, end_arrowhead_stroke: NoneValueType | Color | None = None, end_arrowhead_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, end_arrowhead_stroke_dashoffset: NoneValueType | float | None = None, end_arrowhead_stroke_width: NoneValueType | float | None = None, end_arrowhead_transform: NoneValueType | tuple[Transformation, ...] | None = None, start_arrowhead_fill: NoneValueType | Color | None = None, start_arrowhead_filter: NoneValueType | Filter | None = None, start_arrowhead_stroke: NoneValueType | Color | None = None, start_arrowhead_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, start_arrowhead_stroke_dashoffset: NoneValueType | float | None = None, start_arrowhead_stroke_width: NoneValueType | float | None = None, start_arrowhead_transform: NoneValueType | tuple[Transformation, ...] | None = None)

Bases: Arc

Base class for double-headed arcs.

A double-headed arc is formed of a path and two arrowheads, one at the start of the path and one at its end.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'43533711-e5f3-400d-8e1f-11f0dcd619b9'
layout_elements tuple[LayoutElement, ...]

The sub-layout elements of the group layout. These are part of the children of the group layout

<dynamic>
group_fill NoneValueType | Color | None

The fill color of the group layout

None
group_fill_rule FillRule | None

The fill rule of the group layout

None
group_filter NoneValueType | Filter | None

The filter of the group layout

None
group_font_family str | None

The font family of the group layout

None
group_font_size float | None

The font size of the group layout

None
group_font_style FontStyle | None

The font style of the group layout

None
group_font_weight FontWeight | float | None

The font weight of the group layout

None
group_stroke NoneValueType | Color | None

The stroke color of the group layout

None
group_stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the group layout

None
group_stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the group layout

None
group_stroke_width NoneValueType | float | None

The stroke width of the group layout

None
group_text_anchor TextAnchor | None

The text anchor of the group layout

None
group_transform NoneValueType | tuple[Transformation, ...] | None

The transform of the group layout

None
end_shorten float

The length the end of the arc will be shorten by

0.0
fill NoneValueType | Color | None

The fill color of the arc

None
filter_ NoneValueType | Filter | None

The filter of the arc

None
path_fill NoneValueType | Color | None

The path fill color of the arc

None
path_filter NoneValueType | Filter | None

The path filter of the arc

None
path_stroke NoneValueType | Color | None

The path stroke color of the arc

None
path_stroke_dasharray NoneValueType | tuple[float, ...] | None

The path stroke dasharray of the arc

None
path_stroke_dashoffset NoneValueType | float | None

The path stroke dashoffset of the arc

None
path_stroke_width float | None

The path stroke width of the arc

None
path_transform NoneValueType | tuple[Transformation, ...] | None

The path transform of the arc

None
stroke NoneValueType | Color | None

The stroke color of the arc

None
stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the arc

None
stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the arc

None
stroke_width NoneValueType | float | None

The stroke width of the arc

None
segments tuple[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc, ...]

The path segments of the arc

<dynamic>
source LayoutElement | None

The source of the arc

None
start_shorten float

The length the start of the arc will be shorten by

0.0
target LayoutElement | None

The target of the arc

None
transform NoneValueType | tuple[Transformation, ...] | None

The transform of the arc

None
end_arrowhead_fill NoneValueType | Color | None

The end arrowhead fill color of the arc

None
end_arrowhead_filter NoneValueType | Filter | None

The end arrowhead filter of the arc

None
end_arrowhead_stroke NoneValueType | Color | None

The end arrowhead stroke color of the arc

None
end_arrowhead_stroke_dasharray NoneValueType | tuple[float, ...] | None

The end arrowhead stroke dasharray of the arc

None
end_arrowhead_stroke_dashoffset NoneValueType | float | None

The end arrowhead stroke dashoffset of the arc

None
end_arrowhead_stroke_width NoneValueType | float | None

The end arrowhead stroke width of the arc

None
end_arrowhead_transform NoneValueType | tuple[Transformation, ...] | None

The end arrowhead transform of the arc

None
start_arrowhead_fill NoneValueType | Color | None

The start arrowhead fill color of the arc

None
start_arrowhead_filter NoneValueType | Filter | None

The start arrowhead filter of the arc

None
start_arrowhead_stroke NoneValueType | Color | None

The start arrowhead stroke color of the arc

None
start_arrowhead_stroke_dasharray NoneValueType | tuple[float, ...] | None

The start arrowhead stroke dasharray of the arc

None
start_arrowhead_stroke_dashoffset NoneValueType | float | None

The start arrowhead stroke dashoffset of the arc

None
start_arrowhead_stroke_width NoneValueType | float | None

The start arrowhead stroke width of the arc

None
start_arrowhead_transform NoneValueType | tuple[Transformation, ...] | None

The start arrowhead transform of the arc

None

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

bbox

Compute and return the bounding box of the group layout element.

childless

Return a copy of the arc with no children.

children

Return the children of the group layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the group layout.

end_arrowhead_base

Return the base anchor point of the double-headed arc end arrowhead.

end_arrowhead_bbox

Return the bounding box of the double-headed arc end arrowhead.

end_arrowhead_border

Return the point at the intersection of the drawing elements of the double-headed arc end arrowhead and the line going through the center of these drawing elements and the given point.

end_arrowhead_drawing_elements

Return the drawing elements of the double-headed arc end arrowhead.

end_arrowhead_length

Return the length of the double-headed arc end arrowhead.

end_arrowhead_tip

Return the tip anchor point of the double-headed arc end arrowhead.

end_point

Return the ending point of the arc.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

fraction

Return the position and angle on the arc at a given fraction (of the total arc length).

length

Return the total length of the arc path.

own_bbox

Compute and return the bounding box of the self drawing element of the group layout.

own_children

Return the self children of the arc.

own_drawing_elements

Return the self drawing elements of the double-headed arc. These include the drawing elements of the arc path, the start arrowhead, and the end arrowhead.

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

path_drawing_elements

Return the drawing elements of the double-headed arc path.

points

Return the points of the arc path.

start_arrowhead_base

Return the base anchor point of the double-headed arc start arrowhead.

start_arrowhead_bbox

Return the bounding box of the double-headed arc start arrowhead.

start_arrowhead_border

Return the point at the intersection of the drawing elements of the double-headed arc start arrowhead and the line going through the center of these drawing elements and the given point.

start_arrowhead_drawing_elements

Return the drawing elements of the double-headed arc start arrowhead.

start_arrowhead_length

Return the length of the double-headed arc start arrowhead.

start_arrowhead_tip

Return the tip anchor point of the double-headed arc start arrowhead.

start_point

Return the starting point of the arc.

to_geometry

Return a list of geometry primitives from the drawing elements.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

bbox

bbox() -> Bbox

Compute and return the bounding box of the group layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the group layout element."""
    own_bbox = self.own_bbox()
    bboxes = [child.bbox() for child in self.children()]
    min_x = own_bbox.north_west().x
    min_y = own_bbox.north_west().y
    max_x = own_bbox.south_east().x
    max_y = own_bbox.south_east().y
    for bbox in bboxes:
        if bbox.north_west().x < min_x:
            min_x = bbox.north_west().x
        if bbox.north_west().y < min_y:
            min_y = bbox.north_west().y
        if bbox.south_east().x > max_x:
            max_x = bbox.south_east().x
        if bbox.south_east().y > max_y:
            max_y = bbox.south_east().y
    bbox = Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )
    return bbox

childless

childless() -> Self

Return a copy of the arc with no children.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the arc with no children."""
    return dataclasses.replace(self, layout_elements=tuple([]))

children

children() -> list[LayoutElement]

Return the children of the group layout.

These are the self children of the group layout (returned by the own_children method) and the other children of the group layout (given by the layout_elements attribute).

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the group layout.

    These are the self children of the group layout (returned by the `own_children` method) and the other children of the group layout (given by the `layout_elements` attribute).
    """
    return self.own_children() + list(self.layout_elements)

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the group layout.

The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the group layout.

    The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.
    """
    drawing_elements = self.own_drawing_elements()
    for child in self.children():
        if child is not None:
            drawing_elements += child.drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.group_fill,
        fill_rule=self.group_fill_rule,
        filter_=self.group_filter,
        font_family=self.group_font_family,
        font_size=self.group_font_size,
        font_style=self.group_font_style,
        font_weight=self.group_font_weight,
        stroke=self.group_stroke,
        stroke_dasharray=self.group_stroke_dasharray,
        stroke_dashoffset=self.group_stroke_dashoffset,
        stroke_width=self.group_stroke_width,
        text_anchor=self.group_text_anchor,
        transform=self.group_transform,
    )
    return [group]

end_arrowhead_base

end_arrowhead_base() -> Point

Return the base anchor point of the double-headed arc end arrowhead.

Source code in src/momapy/core/layout.py
def end_arrowhead_base(self) -> Point:
    """Return the base anchor point of the double-headed arc end arrowhead."""
    arrowhead_length = self.end_arrowhead_length()
    if arrowhead_length == 0:
        return self.end_point()
    segment = self.segments[-1]
    segment_length = segment.length()
    if segment_length == 0:
        return self.end_arrowhead_tip() - (arrowhead_length, 0)
    fraction = 1 - (arrowhead_length + self.end_shorten) / segment_length
    return segment.get_position_at_fraction(fraction)

end_arrowhead_bbox

end_arrowhead_bbox() -> Bbox

Return the bounding box of the double-headed arc end arrowhead.

Source code in src/momapy/core/layout.py
def end_arrowhead_bbox(self) -> Bbox:
    """Return the bounding box of the double-headed arc end arrowhead."""
    return get_drawing_elements_bbox(self.end_arrowhead_drawing_elements())

end_arrowhead_border

end_arrowhead_border(point: Point) -> Point

Return the point at the intersection of the drawing elements of the double-headed arc end arrowhead and the line going through the center of these drawing elements and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def end_arrowhead_border(self, point: Point) -> Point:
    """Return the point at the intersection of the drawing elements of the double-headed arc end arrowhead and the line going through the center of these drawing elements and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    point = get_drawing_elements_border(
        self.end_arrowhead_drawing_elements(), point
    )
    if point is None:
        return self.end_arrowhead_tip()
    return point

end_arrowhead_drawing_elements

end_arrowhead_drawing_elements() -> list[DrawingElement]

Return the drawing elements of the double-headed arc end arrowhead.

Source code in src/momapy/core/layout.py
def end_arrowhead_drawing_elements(
    self,
) -> list[DrawingElement]:
    """Return the drawing elements of the double-headed arc end arrowhead."""
    drawing_elements = self._end_arrowhead_border_drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}_end_arrowhead",
        elements=tuple(drawing_elements),
        fill=self.end_arrowhead_fill,
        filter_=self.end_arrowhead_filter,
        id_=f"{self.id_}_end_arrowhead",
        stroke=self.end_arrowhead_stroke,
        stroke_width=self.end_arrowhead_stroke_width,
        stroke_dasharray=self.end_arrowhead_stroke_dasharray,
        stroke_dashoffset=self.end_arrowhead_stroke_dashoffset,
        transform=self.end_arrowhead_transform,
    )
    transformation = self._get_end_arrowhead_transformation()
    group = group.transformed(transformation)
    return [group]

end_arrowhead_length

end_arrowhead_length() -> float

Return the length of the double-headed arc end arrowhead.

Source code in src/momapy/core/layout.py
def end_arrowhead_length(self) -> float:
    """Return the length of the double-headed arc end arrowhead."""
    bbox = get_drawing_elements_bbox(self._end_arrowhead_border_drawing_elements())
    if math.isnan(bbox.width):
        return 0.0
    return bbox.east().x

end_arrowhead_tip

end_arrowhead_tip() -> Point

Return the tip anchor point of the double-headed arc end arrowhead.

Source code in src/momapy/core/layout.py
def end_arrowhead_tip(self) -> Point:
    """Return the tip anchor point of the double-headed arc end arrowhead."""
    segment = self.segments[-1]
    segment_length = segment.length()
    if segment_length == 0:
        return segment.p2
    fraction = 1 - self.end_shorten / segment_length
    return segment.get_position_at_fraction(fraction)

end_point

end_point() -> Point

Return the ending point of the arc.

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def end_point(self) -> Point:
    """Return the ending point of the arc.

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    return self.points()[-1]

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

fraction

fraction(fraction: float) -> tuple[Point, float]

Return the position and angle on the arc at a given fraction (of the total arc length).

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def fraction(self, fraction: float) -> tuple[Point, float]:
    """Return the position and angle on the arc at a given fraction (of the total arc length).

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    current_length = 0
    length_to_reach = fraction * self.length()
    for segment in self.segments:
        current_length += segment.length()
        if current_length >= length_to_reach:
            break
    segment_start_length = current_length - segment.length()
    segment_fraction = (length_to_reach - segment_start_length) / segment.length()
    position, angle = segment.get_position_and_angle_at_fraction(segment_fraction)
    return position, angle

length

length() -> float

Return the total length of the arc path.

Source code in src/momapy/core/layout.py
def length(self) -> float:
    """Return the total length of the arc path."""
    return sum([segment.length() for segment in self.segments])

own_bbox

own_bbox() -> Bbox

Compute and return the bounding box of the self drawing element of the group layout.

Source code in src/momapy/core/layout.py
def own_bbox(self) -> Bbox:
    """Compute and return the bounding box of the self drawing element of the group layout."""
    primitives = self.own_to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

own_children

own_children() -> list[LayoutElement]

Return the self children of the arc.

Source code in src/momapy/core/layout.py
def own_children(self) -> list[LayoutElement]:
    """Return the self children of the arc."""
    return []

own_drawing_elements

own_drawing_elements() -> list[DrawingElement]

Return the self drawing elements of the double-headed arc. These include the drawing elements of the arc path, the start arrowhead, and the end arrowhead.

Source code in src/momapy/core/layout.py
def own_drawing_elements(self) -> list[DrawingElement]:
    """Return the self drawing elements of the double-headed arc. These include the drawing elements of the arc path, the start arrowhead, and the end arrowhead."""
    drawing_elements = (
        self.path_drawing_elements()
        + self.start_arrowhead_drawing_elements()
        + self.end_arrowhead_drawing_elements()
    )

    group = Group(
        class_=f"{type(self).__name__}_own",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}_own",
        fill=self.fill,
        filter_=self.filter_,
        stroke=self.stroke,
        stroke_dasharray=self.stroke_dasharray,
        stroke_dashoffset=self.stroke_dashoffset,
        stroke_width=self.stroke_width,
        transform=self.transform,
    )
    return [group]

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

Source code in src/momapy/core/layout.py
def own_to_geometry(
    self,
) -> list[
    Segment | QuadraticBezierCurve | CubicBezierCurve | GeometryEllipticalArc
]:
    """Return a list of geometry primitives from the self drawing elements."""
    return drawing_elements_to_geometry(self.own_drawing_elements())

path_drawing_elements

path_drawing_elements() -> list[Path]

Return the drawing elements of the double-headed arc path.

Source code in src/momapy/core/layout.py
def path_drawing_elements(self) -> list[Path]:
    """Return the drawing elements of the double-headed arc path."""
    start_arrowhead_length = self.start_arrowhead_length()
    end_arrowhead_length = self.end_arrowhead_length()
    if len(self.segments) == 1:
        segment = (
            self.segments[0]
            .shortened(self.start_shorten + start_arrowhead_length, "start")
            .shortened(self.end_shorten + end_arrowhead_length, "end")
        )
        actions = [
            MoveTo(segment.p1),
            self._make_path_action_from_segment(segment),
        ]
    else:
        first_segment = self.segments[0].shortened(
            self.start_shorten + start_arrowhead_length, "start"
        )
        last_segment = self.segments[-1].shortened(
            self.end_shorten + end_arrowhead_length, "end"
        )
        actions = [
            MoveTo(first_segment.p1),
            self._make_path_action_from_segment(first_segment),
        ]
        for segment in self.segments[1:-1]:
            action = self._make_path_action_from_segment(segment)
            actions.append(action)
        actions.append(self._make_path_action_from_segment(last_segment))
    path = Path(
        actions=tuple(actions),
        class_=f"{type(self).__name__}_path",
        fill=self.path_fill,
        filter_=self.path_filter,
        id_=f"{self.id_}_path",
        stroke=self.path_stroke,
        stroke_dasharray=self.path_stroke_dasharray,
        stroke_dashoffset=self.path_stroke_dashoffset,
        stroke_width=self.path_stroke_width,
        transform=self.path_transform,
    )
    return [path]

points

points() -> list[Point]

Return the points of the arc path.

An arc with no segments has no points and returns an empty list.

Source code in src/momapy/core/layout.py
def points(self) -> list[Point]:
    """Return the points of the arc path.

    An arc with no segments has no points and returns an empty list.
    """
    if not self.segments:
        return []
    points = []
    for segment in self.segments:
        points.append(segment.p1)
    points.append(segment.p2)
    return points

start_arrowhead_base

start_arrowhead_base() -> Point

Return the base anchor point of the double-headed arc start arrowhead.

Source code in src/momapy/core/layout.py
def start_arrowhead_base(self) -> Point:
    """Return the base anchor point of the double-headed arc start arrowhead."""
    arrowhead_length = self.start_arrowhead_length()
    if arrowhead_length == 0:
        return self.start_point()
    segment = self.segments[0]
    segment = Segment(segment.p2, segment.p1)
    segment_length = segment.length()
    if segment_length == 0:
        return self.start_arrowhead_tip() + (arrowhead_length, 0)
    fraction = 1 - (arrowhead_length + self.start_shorten) / segment_length
    return segment.get_position_at_fraction(fraction)

start_arrowhead_bbox

start_arrowhead_bbox() -> Bbox

Return the bounding box of the double-headed arc start arrowhead.

Source code in src/momapy/core/layout.py
def start_arrowhead_bbox(self) -> Bbox:
    """Return the bounding box of the double-headed arc start arrowhead."""
    return get_drawing_elements_bbox(self.start_arrowhead_drawing_elements())

start_arrowhead_border

start_arrowhead_border(point: Point) -> Point

Return the point at the intersection of the drawing elements of the double-headed arc start arrowhead and the line going through the center of these drawing elements and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def start_arrowhead_border(self, point: Point) -> Point:
    """Return the point at the intersection of the drawing elements of the double-headed arc start arrowhead and the line going through the center of these drawing elements and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    point = get_drawing_elements_border(
        self.start_arrowhead_drawing_elements(), point
    )
    if point is None:
        return self.start_arrowhead_tip()
    return point

start_arrowhead_drawing_elements

start_arrowhead_drawing_elements() -> list[DrawingElement]

Return the drawing elements of the double-headed arc start arrowhead.

Source code in src/momapy/core/layout.py
def start_arrowhead_drawing_elements(
    self,
) -> list[DrawingElement]:
    """Return the drawing elements of the double-headed arc start arrowhead."""
    drawing_elements = self._start_arrowhead_border_drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}_start_arrowhead",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}_start_arrowhead",
        fill=self.start_arrowhead_fill,
        filter_=self.start_arrowhead_filter,
        stroke=self.start_arrowhead_stroke,
        stroke_dasharray=self.start_arrowhead_stroke_dasharray,
        stroke_dashoffset=self.start_arrowhead_stroke_dashoffset,
        stroke_width=self.start_arrowhead_stroke_width,
        transform=self.start_arrowhead_transform,
    )
    transformation = self._get_start_arrowhead_transformation()
    group = group.transformed(transformation)
    return [group]

start_arrowhead_length

start_arrowhead_length() -> float

Return the length of the double-headed arc start arrowhead.

Source code in src/momapy/core/layout.py
def start_arrowhead_length(self) -> float:
    """Return the length of the double-headed arc start arrowhead."""
    bbox = get_drawing_elements_bbox(
        self._start_arrowhead_border_drawing_elements()
    )
    if math.isnan(bbox.width):
        return 0.0
    return abs(bbox.west().x)

start_arrowhead_tip

start_arrowhead_tip() -> Point

Return the tip anchor point of the double-headed arc start arrowhead.

Source code in src/momapy/core/layout.py
def start_arrowhead_tip(self) -> Point:
    """Return the tip anchor point of the double-headed arc start arrowhead."""
    segment = self.segments[0]
    segment = Segment(segment.p2, segment.p1)
    segment_length = segment.length()
    if segment_length == 0:
        return segment.p2
    fraction = 1 - self.start_shorten / segment_length
    return segment.get_position_at_fraction(fraction)

start_point

start_point() -> Point

Return the starting point of the arc.

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def start_point(self) -> Point:
    """Return the starting point of the arc.

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    return self.points()[0]

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

GroupLayout dataclass

GroupLayout(*, id_: str = make_uuid4_as_str(), layout_elements: tuple[LayoutElement, ...] = tuple(), group_fill: NoneValueType | Color | None = None, group_fill_rule: FillRule | None = None, group_filter: NoneValueType | Filter | None = None, group_font_family: str | None = None, group_font_size: float | None = None, group_font_style: FontStyle | None = None, group_font_weight: FontWeight | float | None = None, group_stroke: NoneValueType | Color | None = None, group_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, group_stroke_dashoffset: NoneValueType | float | None = None, group_stroke_width: NoneValueType | float | None = None, group_text_anchor: TextAnchor | None = None, group_transform: NoneValueType | tuple[Transformation, ...] | None = None)

Bases: LayoutElement

Base class for group layouts.

A group layout is a layout element grouping other layout elements, with its own drawing elements and children combined into a single group drawing element.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'29a3e580-2115-4caf-ba20-4a9ce7105956'
layout_elements tuple[LayoutElement, ...]

The sub-layout elements of the group layout. These are part of the children of the group layout

<dynamic>
group_fill NoneValueType | Color | None

The fill color of the group layout

None
group_fill_rule FillRule | None

The fill rule of the group layout

None
group_filter NoneValueType | Filter | None

The filter of the group layout

None
group_font_family str | None

The font family of the group layout

None
group_font_size float | None

The font size of the group layout

None
group_font_style FontStyle | None

The font style of the group layout

None
group_font_weight FontWeight | float | None

The font weight of the group layout

None
group_stroke NoneValueType | Color | None

The stroke color of the group layout

None
group_stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the group layout

None
group_stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the group layout

None
group_stroke_width NoneValueType | float | None

The stroke width of the group layout

None
group_text_anchor TextAnchor | None

The text anchor of the group layout

None
group_transform NoneValueType | tuple[Transformation, ...] | None

The transform of the group layout

None

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

bbox

Compute and return the bounding box of the group layout element.

childless

Return a copy of the layout element with no children.

children

Return the children of the group layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the group layout.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

own_bbox

Compute and return the bounding box of the self drawing element of the group layout.

own_children

Return the self children of the group layout.

own_drawing_elements

Return the self drawing elements of the group layout.

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

to_geometry

Return a list of geometry primitives from the drawing elements.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

bbox

bbox() -> Bbox

Compute and return the bounding box of the group layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the group layout element."""
    own_bbox = self.own_bbox()
    bboxes = [child.bbox() for child in self.children()]
    min_x = own_bbox.north_west().x
    min_y = own_bbox.north_west().y
    max_x = own_bbox.south_east().x
    max_y = own_bbox.south_east().y
    for bbox in bboxes:
        if bbox.north_west().x < min_x:
            min_x = bbox.north_west().x
        if bbox.north_west().y < min_y:
            min_y = bbox.north_west().y
        if bbox.south_east().x > max_x:
            max_x = bbox.south_east().x
        if bbox.south_east().y > max_y:
            max_y = bbox.south_east().y
    bbox = Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )
    return bbox

childless abstractmethod

childless() -> Self

Return a copy of the layout element with no children.

Source code in src/momapy/core/elements.py
@abc.abstractmethod
def childless(self) -> typing_extensions.Self:
    """Return a copy of the layout element with no children."""
    pass

children

children() -> list[LayoutElement]

Return the children of the group layout.

These are the self children of the group layout (returned by the own_children method) and the other children of the group layout (given by the layout_elements attribute).

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the group layout.

    These are the self children of the group layout (returned by the `own_children` method) and the other children of the group layout (given by the `layout_elements` attribute).
    """
    return self.own_children() + list(self.layout_elements)

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the group layout.

The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the group layout.

    The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.
    """
    drawing_elements = self.own_drawing_elements()
    for child in self.children():
        if child is not None:
            drawing_elements += child.drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.group_fill,
        fill_rule=self.group_fill_rule,
        filter_=self.group_filter,
        font_family=self.group_font_family,
        font_size=self.group_font_size,
        font_style=self.group_font_style,
        font_weight=self.group_font_weight,
        stroke=self.group_stroke,
        stroke_dasharray=self.group_stroke_dasharray,
        stroke_dashoffset=self.group_stroke_dashoffset,
        stroke_width=self.group_stroke_width,
        text_anchor=self.group_text_anchor,
        transform=self.group_transform,
    )
    return [group]

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

own_bbox

own_bbox() -> Bbox

Compute and return the bounding box of the self drawing element of the group layout.

Source code in src/momapy/core/layout.py
def own_bbox(self) -> Bbox:
    """Compute and return the bounding box of the self drawing element of the group layout."""
    primitives = self.own_to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

own_children abstractmethod

own_children() -> list[LayoutElement]

Return the self children of the group layout.

Source code in src/momapy/core/layout.py
@abc.abstractmethod
def own_children(self) -> list[LayoutElement]:
    """Return the self children of the group layout."""
    pass

own_drawing_elements abstractmethod

own_drawing_elements() -> list[DrawingElement]

Return the self drawing elements of the group layout.

Source code in src/momapy/core/layout.py
@abc.abstractmethod
def own_drawing_elements(self) -> list[DrawingElement]:
    """Return the self drawing elements of the group layout."""
    pass

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

Source code in src/momapy/core/layout.py
def own_to_geometry(
    self,
) -> list[
    Segment | QuadraticBezierCurve | CubicBezierCurve | GeometryEllipticalArc
]:
    """Return a list of geometry primitives from the self drawing elements."""
    return drawing_elements_to_geometry(self.own_drawing_elements())

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

HAlignment

Bases: Enum

Horizontal alignment of text or content.

Selects how content is positioned along the horizontal axis.

Layout dataclass

Layout(*, id_: str = make_uuid4_as_str(), layout_elements: tuple[LayoutElement, ...] = tuple(), group_fill: NoneValueType | Color | None = None, group_fill_rule: FillRule | None = None, group_filter: NoneValueType | Filter | None = None, group_font_family: str | None = None, group_font_size: float | None = None, group_font_style: FontStyle | None = None, group_font_weight: FontWeight | float | None = None, group_stroke: NoneValueType | Color | None = None, group_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, group_stroke_dashoffset: NoneValueType | float | None = None, group_stroke_width: NoneValueType | float | None = None, group_text_anchor: TextAnchor | None = None, group_transform: NoneValueType | tuple[Transformation, ...] | None = None, fill: NoneValueType | Color | None = NoneValue, filter_: NoneValueType | Filter | None = None, height: float, label: TextLayout | None = None, position: Point, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, transform: NoneValueType | tuple[Transformation, ...] | None = None, width: float)

Bases: Node

Class for layouts.

A layout is the root node holding all the visual elements of a map.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'1c93e7de-4215-4b0e-8e2f-9fd69ed7c57b'
layout_elements tuple[LayoutElement, ...]

The sub-layout elements of the group layout. These are part of the children of the group layout

<dynamic>
group_fill NoneValueType | Color | None

The fill color of the group layout

None
group_fill_rule FillRule | None

The fill rule of the group layout

None
group_filter NoneValueType | Filter | None

The filter of the group layout

None
group_font_family str | None

The font family of the group layout

None
group_font_size float | None

The font size of the group layout

None
group_font_style FontStyle | None

The font style of the group layout

None
group_font_weight FontWeight | float | None

The font weight of the group layout

None
group_stroke NoneValueType | Color | None

The stroke color of the group layout

None
group_stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the group layout

None
group_stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the group layout

None
group_stroke_width NoneValueType | float | None

The stroke width of the group layout

None
group_text_anchor TextAnchor | None

The text anchor of the group layout

None
group_transform NoneValueType | tuple[Transformation, ...] | None

The transform of the group layout

None
fill NoneValueType | Color | None

The fill color of the node

<momapy.drawing.NoneValueType object at 0x7fb1b7eb96a0>
filter_ NoneValueType | Filter | None

The filter of the node

None
height float

The height of the node

required
label TextLayout | None

The label of the node

None
position Point

The position of the node

required
stroke NoneValueType | Color | None

The stroke color of the node

None
stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the node

None
stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the node

None
stroke_width NoneValueType | float | None

The stroke width of the node

None
transform NoneValueType | tuple[Transformation, ...] | None

The transform of the node

None
width float

The width of the node

required

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

angle

Return the point on the border of the node that intersects the drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

bbox

Compute and return the bounding box of the group layout element.

border

Return the point on the border of the node that intersects the drawing elements of the node with the line formed of the center anchor point of the node and the given point.

center

Return the center anchor of the node.

childless

Return a copy of the node with no children.

children

Return the children of the group layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the group layout.

east

Return the east anchor of the node.

east_north_east

Return the east north east anchor of the node.

east_south_east

Return the east south east anchor of the node.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

is_sublayout

Return True if the layout is a sublayout of another given layout, False otherwise.

label_center

Return the label center anchor of the node.

north

Return the north anchor of the node.

north_east

Return the north east anchor of the node.

north_north_east

Return the north north east anchor of the node.

north_north_west

Return the north north west anchor of the node.

north_west

Return the north west anchor of the node.

own_angle

Return the point on the border of the node that intersects the self drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

own_bbox

Compute and return the bounding box of the self drawing element of the group layout.

own_border

Return the point on the border of the node that intersects the self drawing elements of the node with the line formed of the center anchor point of the node and the given point.

own_children

Return the self children of the node. A node has unique child that is its label.

own_drawing_elements

Return the node's own drawing elements.

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

size

Return the size of the node.

south

Return the south anchor of the node.

south_east

Return the south east anchor of the node.

south_south_east

Return the south south east anchor of the node.

south_south_west

Return the south south west anchor of the node.

south_west

Return the south west anchor of the node.

to_geometry

Return a list of geometry primitives from the drawing elements.

west

Return the west anchor of the node.

west_north_west

Return the west north west anchor of the node.

west_south_west

Return the west south west anchor of the node.

Attributes:

Name Type Description
x float

Return the x coordinate of the node.

y float

Return the y coordinate of the node.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

angle

angle(angle: float, unit: Literal['degrees', 'radians'] = 'degrees') -> Point | None

Return the point on the border of the node that intersects the drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

Source code in src/momapy/core/layout.py
def angle(
    self,
    angle: float,
    unit: typing.Literal["degrees", "radians"] = "degrees",
) -> Point | None:
    """Return the point on the border of the node that intersects the drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal."""
    return get_drawing_elements_angle(
        drawing_elements=self.drawing_elements(),
        angle=angle,
        unit=unit,
        center=self.center(),
    )

bbox

bbox() -> Bbox

Compute and return the bounding box of the group layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the group layout element."""
    own_bbox = self.own_bbox()
    bboxes = [child.bbox() for child in self.children()]
    min_x = own_bbox.north_west().x
    min_y = own_bbox.north_west().y
    max_x = own_bbox.south_east().x
    max_y = own_bbox.south_east().y
    for bbox in bboxes:
        if bbox.north_west().x < min_x:
            min_x = bbox.north_west().x
        if bbox.north_west().y < min_y:
            min_y = bbox.north_west().y
        if bbox.south_east().x > max_x:
            max_x = bbox.south_east().x
        if bbox.south_east().y > max_y:
            max_y = bbox.south_east().y
    bbox = Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )
    return bbox

border

border(point: Point) -> Point | None

Return the point on the border of the node that intersects the drawing elements of the node with the line formed of the center anchor point of the node and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def border(self, point: Point) -> Point | None:
    """Return the point on the border of the node that intersects the drawing elements of the node with the line formed of the center anchor point of the node and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    return get_drawing_elements_border(
        drawing_elements=self.drawing_elements(),
        point=point,
        center=self.center(),
    )

center

center() -> Point

Return the center anchor of the node.

Source code in src/momapy/core/layout.py
def center(self) -> Point:
    """Return the center anchor of the node."""
    return self.position

childless

childless() -> Self

Return a copy of the node with no children.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the node with no children."""
    return dataclasses.replace(self, label=None, layout_elements=tuple([]))

children

children() -> list[LayoutElement]

Return the children of the group layout.

These are the self children of the group layout (returned by the own_children method) and the other children of the group layout (given by the layout_elements attribute).

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the group layout.

    These are the self children of the group layout (returned by the `own_children` method) and the other children of the group layout (given by the `layout_elements` attribute).
    """
    return self.own_children() + list(self.layout_elements)

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the group layout.

The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the group layout.

    The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.
    """
    drawing_elements = self.own_drawing_elements()
    for child in self.children():
        if child is not None:
            drawing_elements += child.drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.group_fill,
        fill_rule=self.group_fill_rule,
        filter_=self.group_filter,
        font_family=self.group_font_family,
        font_size=self.group_font_size,
        font_style=self.group_font_style,
        font_weight=self.group_font_weight,
        stroke=self.group_stroke,
        stroke_dasharray=self.group_stroke_dasharray,
        stroke_dashoffset=self.group_stroke_dashoffset,
        stroke_width=self.group_stroke_width,
        text_anchor=self.group_text_anchor,
        transform=self.group_transform,
    )
    return [group]

east

east() -> Point

Return the east anchor of the node.

Source code in src/momapy/core/layout.py
def east(self) -> Point:
    """Return the east anchor of the node."""
    return self.own_angle(0)

east_north_east

east_north_east() -> Point

Return the east north east anchor of the node.

Source code in src/momapy/core/layout.py
def east_north_east(self) -> Point:
    """Return the east north east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, -self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

east_south_east

east_south_east() -> Point

Return the east south east anchor of the node.

Source code in src/momapy/core/layout.py
def east_south_east(self) -> Point:
    """Return the east south east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

is_sublayout

is_sublayout(other: Layout, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout is a sublayout of another given layout, False otherwise.

Source code in src/momapy/core/layout.py
def is_sublayout(
    self, other: "Layout", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout is a sublayout of another given layout, `False` otherwise."""

    def _is_sublist(
        list1: list[LayoutElement],
        list2: list[LayoutElement],
        unordered: bool = False,
    ) -> bool:
        if not unordered:
            i = 0
            for elem1 in list1:
                elem2 = list2[i]
                while elem2 != elem1 and i < len(list2) - 1:
                    i += 1
                    elem2 = list2[i]
                if not elem2 == elem1:
                    return False
                i += 1
        else:
            dlist1 = collections.defaultdict(int)
            dlist2 = collections.defaultdict(int)
            for elem1 in list1:
                dlist1[elem1] += 1
            for elem2 in list2:
                dlist2[elem2] += 1
            for elem in dlist1:
                if dlist1[elem] > dlist2[elem]:
                    return False
        return True

    if self.childless() != other.childless():
        return False
    if flattened:
        return _is_sublist(
            self.flattened()[1:],
            other.flattened()[1:],
            unordered=unordered,
        )
    return _is_sublist(self.children(), other.children(), unordered=unordered)

label_center

label_center() -> Point

Return the label center anchor of the node.

Source code in src/momapy/core/layout.py
def label_center(self) -> Point:
    """Return the label center anchor of the node."""
    return self.position

north

north() -> Point

Return the north anchor of the node.

Source code in src/momapy/core/layout.py
def north(self) -> Point:
    """Return the north anchor of the node."""
    return self.own_angle(90)

north_east

north_east() -> Point

Return the north east anchor of the node.

Source code in src/momapy/core/layout.py
def north_east(self) -> Point:
    """Return the north east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, -self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

north_north_east

north_north_east() -> Point

Return the north north east anchor of the node.

Source code in src/momapy/core/layout.py
def north_north_east(self) -> Point:
    """Return the north north east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 4, -self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

north_north_west

north_north_west() -> Point

Return the north north west anchor of the node.

Source code in src/momapy/core/layout.py
def north_north_west(self) -> Point:
    """Return the north north west anchor of the node."""
    line = Line(self.center(), self.center() - (self.width / 4, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

north_west

north_west() -> Point

Return the north west anchor of the node.

Source code in src/momapy/core/layout.py
def north_west(self) -> Point:
    """Return the north west anchor of the node."""
    line = Line(self.center(), self.center() - (self.width / 2, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

own_angle

own_angle(angle: float, unit: Literal['degrees', 'radians'] = 'degrees') -> Point | None

Return the point on the border of the node that intersects the self drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

Source code in src/momapy/core/layout.py
def own_angle(
    self,
    angle: float,
    unit: typing.Literal["degrees", "radians"] = "degrees",
) -> Point | None:
    """Return the point on the border of the node that intersects the self drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal."""
    return get_drawing_elements_angle(
        drawing_elements=self.own_drawing_elements(),
        angle=angle,
        unit=unit,
        center=self.center(),
    )

own_bbox

own_bbox() -> Bbox

Compute and return the bounding box of the self drawing element of the group layout.

Source code in src/momapy/core/layout.py
def own_bbox(self) -> Bbox:
    """Compute and return the bounding box of the self drawing element of the group layout."""
    primitives = self.own_to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

own_border

own_border(point: Point) -> Point | None

Return the point on the border of the node that intersects the self drawing elements of the node with the line formed of the center anchor point of the node and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def own_border(self, point: Point) -> Point | None:
    """Return the point on the border of the node that intersects the self drawing elements of the node with the line formed of the center anchor point of the node and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    return get_drawing_elements_border(
        drawing_elements=self.own_drawing_elements(),
        point=point,
        center=self.center(),
    )

own_children

own_children() -> list[LayoutElement]

Return the self children of the node. A node has unique child that is its label.

Source code in src/momapy/core/layout.py
def own_children(self) -> list[LayoutElement]:
    """Return the self children of the node. A node has unique child that is its label."""
    if self.label is not None:
        return [self.label]
    return []

own_drawing_elements

own_drawing_elements() -> list[DrawingElement]

Return the node's own drawing elements.

Source code in src/momapy/core/layout.py
def own_drawing_elements(self) -> list[DrawingElement]:
    """Return the node's own drawing elements."""
    drawing_elements = self._border_drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}_own",
        elements=tuple(drawing_elements),
        fill=self.fill,
        filter_=self.filter_,
        id_=f"{self.id_}_own",
        stroke=self.stroke,
        stroke_dasharray=self.stroke_dasharray,
        stroke_dashoffset=self.stroke_dashoffset,
        stroke_width=self.stroke_width,
        transform=self.transform,
    )
    return [group]

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

Source code in src/momapy/core/layout.py
def own_to_geometry(
    self,
) -> list[
    Segment | QuadraticBezierCurve | CubicBezierCurve | GeometryEllipticalArc
]:
    """Return a list of geometry primitives from the self drawing elements."""
    return drawing_elements_to_geometry(self.own_drawing_elements())

size

size() -> tuple[float, float]

Return the size of the node.

Source code in src/momapy/core/layout.py
def size(self) -> tuple[float, float]:
    """Return the size of the node."""
    return (self.width, self.height)

south

south() -> Point

Return the south anchor of the node.

Source code in src/momapy/core/layout.py
def south(self) -> Point:
    """Return the south anchor of the node."""
    return self.own_angle(270)

south_east

south_east() -> Point

Return the south east anchor of the node.

Source code in src/momapy/core/layout.py
def south_east(self) -> Point:
    """Return the south east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

south_south_east

south_south_east() -> Point

Return the south south east anchor of the node.

Source code in src/momapy/core/layout.py
def south_south_east(self) -> Point:
    """Return the south south east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 4, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

south_south_west

south_south_west() -> Point

Return the south south west anchor of the node.

Source code in src/momapy/core/layout.py
def south_south_west(self) -> Point:
    """Return the south south west anchor of the node."""
    line = Line(self.center(), self.center() + (-self.width / 4, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

south_west

south_west() -> Point

Return the south west anchor of the node.

Source code in src/momapy/core/layout.py
def south_west(self) -> Point:
    """Return the south west anchor of the node."""
    line = Line(self.center(), self.center() + (-self.width / 2, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

west

west() -> Point

Return the west anchor of the node.

Source code in src/momapy/core/layout.py
def west(self) -> Point:
    """Return the west anchor of the node."""
    return self.own_angle(180)

west_north_west

west_north_west() -> Point

Return the west north west anchor of the node.

Source code in src/momapy/core/layout.py
def west_north_west(self) -> Point:
    """Return the west north west anchor of the node."""
    line = Line(self.center(), self.center() - (self.width / 2, self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

west_south_west

west_south_west() -> Point

Return the west south west anchor of the node.

Source code in src/momapy/core/layout.py
def west_south_west(self) -> Point:
    """Return the west south west anchor of the node."""
    line = Line(self.center(), self.center() + (-self.width / 2, self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

x property

x: float

Return the x coordinate of the node.

y property

y: float

Return the y coordinate of the node.

LayoutElement dataclass

LayoutElement(*, id_: str = make_uuid4_as_str())

Bases: MapElement, ABC

Abstract base class for layout elements.

Common ancestor of every element carrying the visual information of a map.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'd6fe6e30-9d57-4758-b767-a2360053346f'

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

bbox

Compute and return the bounding box of the layout element.

childless

Return a copy of the layout element with no children.

children

Return the children of the layout element.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the layout element.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

to_geometry

Return a list of geometry primitives from the drawing elements.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

bbox abstractmethod

bbox() -> Bbox

Compute and return the bounding box of the layout element.

Source code in src/momapy/core/elements.py
@abc.abstractmethod
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the layout element."""
    pass

childless abstractmethod

childless() -> Self

Return a copy of the layout element with no children.

Source code in src/momapy/core/elements.py
@abc.abstractmethod
def childless(self) -> typing_extensions.Self:
    """Return a copy of the layout element with no children."""
    pass

children abstractmethod

children() -> list[LayoutElement]

Return the children of the layout element.

Source code in src/momapy/core/elements.py
@abc.abstractmethod
def children(self) -> list["LayoutElement"]:
    """Return the children of the layout element."""
    pass

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements abstractmethod

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the layout element.

Source code in src/momapy/core/elements.py
@abc.abstractmethod
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the layout element."""
    pass

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

LayoutModelMapping

LayoutModelMapping(*args, **kwargs)

Bases: FrozenIdentitySurjectionDict

Mapping between model elements and layout elements.

A Map can draw the same model element several times, so the relation between layouts and model elements is a many-to-one mapping whose keys are layout elements and whose values are model elements. Two kinds of keys are used:

  • Singleton key — a single LayoutElement that represents a model element on its own (a macromolecule glyph, a compartment, a state variable, a modulation arc when no cluster is needed).
  • Frozenset key — a frozenset of several layout elements that jointly represent one model element. Used whenever a model concept is drawn as a cluster of shapes: a process and its participant arcs and target layouts, a logical operator and its input arcs and targets, a modulation arc with its source and target clusters, a tag or terminal with its reference arcs.

When the key is a frozenset, it is useful to designate one of the layouts as the representative — the element that stands for the cluster on its own. The representative is typically the "central" layout (the process glyph for a process, the operator glyph for a logical operator, the modulation arc for a modulation, the tag glyph for a tag). Representatives are registered through the representative argument of add_mapping. Once registered, get_mapping resolves the representative back to the model element stored under the frozenset key, and other composite keys can reference the cluster by its representative rather than by the whole frozenset.

See the SBGN-PD, SBGN-AF, and CellDesigner module documentation for the per-model-element catalogue of key shapes and representatives.

Initialize the mapping and its frozen representative index.

Methods:

Name Description
__reduce__

Pickle hook that preserves _representative_to_key across round-trips.

__setstate__

Restore _representative_to_key after __reduce__-driven unpickle.

get_child_layout_elements

Return the layout elements representing child_model_element under parent_model_element.

get_mapping

Return the model element or layout elements mapped to map_element.

is_submapping

Return True if the mapping is a submapping of another LayoutModelMapping, False otherwise.

Attributes:

Name Type Description
inverse frozendict

Return the value->keys inverse as a frozendict[K, frozenset].

representative_to_key FrozenSurjectionDict

Return the read-only table mapping representatives to frozenset keys.

Source code in src/momapy/core/mapping.py
def __init__(self, *args, **kwargs) -> None:
    """Initialize the mapping and its frozen representative index."""
    super().__init__(*args, **kwargs)
    object.__setattr__(
        self,
        "_representative_to_key",
        FrozenSurjectionDict(),
    )

__reduce__

__reduce__() -> tuple[Any, ...]

Pickle hook that preserves _representative_to_key across round-trips.

The inherited frozendict.__reduce__ only serialises the dict contents, which drops the representative table added by this subclass.

Source code in src/momapy/core/mapping.py
def __reduce__(self) -> tuple[typing.Any, ...]:
    """Pickle hook that preserves `_representative_to_key` across round-trips.

    The inherited `frozendict.__reduce__` only serialises the dict
    contents, which drops the representative table added by this subclass.
    """
    return (
        type(self),
        (dict(self),),
        {"_representative_to_key": dict(self._representative_to_key)},
    )

__setstate__

__setstate__(state: dict[str, Any]) -> None

Restore _representative_to_key after __reduce__-driven unpickle.

Source code in src/momapy/core/mapping.py
def __setstate__(self, state: dict[str, typing.Any]) -> None:
    """Restore `_representative_to_key` after `__reduce__`-driven unpickle."""
    object.__setattr__(
        self,
        "_representative_to_key",
        FrozenSurjectionDict(state["_representative_to_key"]),
    )

get_child_layout_elements

get_child_layout_elements(child_model_element: ModelElement, parent_model_element: ModelElement) -> list[LayoutElement]

Return the layout elements representing child_model_element under parent_model_element.

Computes the intersection of two sets:

  • S1: layouts that belong under parent_model_element — the children of each container layout mapped to the parent, plus the members of each frozenset key mapped to the parent.
  • S2: layouts that represent child_model_element — each singleton layout mapped to the child, plus the representatives of each frozenset key mapped to the child.

The inverse is identity-keyed, so two content-equal but id-distinct model instances are not aliased: layouts under one parent do not cross-pollute the result for the sibling instance.

Source code in src/momapy/core/mapping.py
def get_child_layout_elements(
    self,
    child_model_element: "ModelElement",
    parent_model_element: "ModelElement",
) -> "list[LayoutElement]":
    """Return the layout elements representing ``child_model_element`` under ``parent_model_element``.

    Computes the intersection of two sets:

    - ``S1``: layouts that belong under ``parent_model_element`` — the
      children of each container layout mapped to the parent, plus the
      members of each frozenset key mapped to the parent.
    - ``S2``: layouts that represent ``child_model_element`` — each
      singleton layout mapped to the child, plus the representatives of each
      frozenset key mapped to the child.

    The inverse is identity-keyed, so two content-equal but id-distinct
    model instances are not aliased: layouts under one parent do not
    cross-pollute the result for the sibling instance.
    """
    child_s2 = set()
    for key in self.inverse.get(id(child_model_element), ()):
        if isinstance(key, frozenset):
            for representative in self._representative_to_key.inverse.get(key, []):
                child_s2.add(representative)
        else:
            child_s2.add(key)
    parent_s1 = set()
    for parent_layout in self.inverse.get(id(parent_model_element), ()):
        if isinstance(parent_layout, frozenset):
            parent_s1 |= parent_layout
        elif hasattr(parent_layout, "layout_elements"):
            parent_s1.update(parent_layout.layout_elements)
    return list(parent_s1 & child_s2)

get_mapping

get_mapping(map_element: MapElement) -> ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None

Return the model element or layout elements mapped to map_element.

Lookup order: 1. Direct key: map_element is a singleton or frozenset key in the mapping; returns the associated model element directly. 2. Inverse: map_element is a model element; returns the list of layout elements (or frozenset keys) whose stored model value is map_element by object identity. Two content-equal but id-distinct model instances are not aliased. 3. Representative fallback: map_element was registered as the representative of a frozenset key via the representative argument of add_mapping; returns the model element stored under that frozenset key.

Returns None when no match is found.

Source code in src/momapy/core/mapping.py
def get_mapping(
    self,
    map_element: "MapElement",
) -> "ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None":
    """Return the model element or layout elements mapped to `map_element`.

    Lookup order:
    1. Direct key: `map_element` is a singleton or frozenset key in the
       mapping; returns the associated model element directly.
    2. Inverse: `map_element` is a model element; returns the list of
       layout elements (or frozenset keys) whose stored model value
       **is** ``map_element`` by object identity. Two content-equal
       but id-distinct model instances are *not* aliased.
    3. Representative fallback: `map_element` was registered as the representative of a
       frozenset key via the ``representative`` argument of ``add_mapping``;
       returns the model element stored under that frozenset key.

    Returns ``None`` when no match is found.
    """
    if map_element in self:
        return self[map_element]
    result = self.inverse.get(id(map_element))
    if result:
        return list(result)
    key = self._representative_to_key.get(map_element)
    if key is not None:
        return self[key]
    return None

inverse property

inverse: frozendict

Return the value->keys inverse as a frozendict[K, frozenset].

K is the value (equality variants) or id(value) (identity variants); each bucket is a frozenset of forward keys. It is precomputed once at construction and returned in O(1).

Returns:

Type Description
frozendict

A frozendict mapping each value (or id(value)) to the

frozendict

frozenset of keys that map to it.

is_submapping

is_submapping(other: LayoutModelMapping) -> bool

Return True if the mapping is a submapping of another LayoutModelMapping, False otherwise.

Source code in src/momapy/core/mapping.py
def is_submapping(self, other: "LayoutModelMapping") -> bool:
    """Return `True` if the mapping is a submapping of another `LayoutModelMapping`, `False` otherwise."""
    return self.items() <= other.items()

representative_to_key property

representative_to_key: FrozenSurjectionDict

Return the read-only table mapping representatives to frozenset keys.

LayoutModelMappingBuilder

LayoutModelMappingBuilder(*args, **kwargs)

Bases: IdentitySurjectionDict, Builder

Mutable builder for LayoutModelMapping.

Builds a layout-to-model mapping incrementally, then produces a frozen LayoutModelMapping via build(). It keeps the same key conventions as the frozen mapping (singleton layout keys and frozenset keys, each frozenset with a representative registered in _representative_to_key), but uses mutable containers so elements can be added or replaced while a map is being constructed.

Initialize the mapping builder and its representative index.

Methods:

Name Description
__delitem__

Delete a key, updating the identity-keyed inverse index.

__reduce__

Pickle hook that preserves _representative_to_key across round-trips.

__setitem__

Set a key to a value, updating the identity-keyed inverse index.

__setstate__

Restore _representative_to_key after __reduce__-driven unpickle.

add_mapping

Add a layout-element to model-element entry to the mapping.

build

Build a frozen LayoutModelMapping from this builder.

from_object

Build a LayoutModelMappingBuilder from a frozen mapping.

get_child_layout_elements

Return the layout elements representing child_model_element under parent_model_element.

get_mapping

Return the element(s) mapped to the given map element.

Attributes:

Name Type Description
inverse frozendict

Return the value->keys inverse as a frozendict[K, frozenset].

representative_to_key SurjectionDict

Return the table mapping representatives to frozenset keys.

Source code in src/momapy/core/mapping.py
def __init__(self, *args, **kwargs) -> None:
    """Initialize the mapping builder and its representative index."""
    super().__init__(*args, **kwargs)
    self._representative_to_key = SurjectionDict()

__delitem__

__delitem__(key: Any) -> None

Delete a key, updating the identity-keyed inverse index.

Source code in src/momapy/utils.py
def __delitem__(self, key: typing.Any) -> None:
    """Delete a key, updating the identity-keyed inverse index."""
    value = self[key]
    value_identity = id(value)
    super().__delitem__(key)
    if value_identity in self._identity_inverse:
        self._identity_inverse[value_identity].discard(key)
        if not self._identity_inverse[value_identity]:
            del self._identity_inverse[value_identity]

__reduce__

__reduce__() -> tuple[Any, ...]

Pickle hook that preserves _representative_to_key across round-trips.

The default dict-subclass pickle emits SETITEMS before BUILD, so IdentitySurjectionDict.__setitem__ fires before _identity_inverse exists and crashes. Routing through __init__ fixes both that and the _representative_to_key loss.

Source code in src/momapy/core/mapping.py
def __reduce__(self) -> tuple[typing.Any, ...]:
    """Pickle hook that preserves `_representative_to_key` across round-trips.

    The default `dict`-subclass pickle emits SETITEMS before BUILD, so
    `IdentitySurjectionDict.__setitem__` fires before
    `_identity_inverse` exists and crashes. Routing through
    `__init__` fixes both that and the `_representative_to_key` loss.
    """
    return (
        type(self),
        (dict(self),),
        {"_representative_to_key": dict(self._representative_to_key)},
    )

__setitem__

__setitem__(key: Any, value: Any) -> None

Set a key to a value, updating the identity-keyed inverse index.

Source code in src/momapy/utils.py
def __setitem__(self, key: typing.Any, value: typing.Any) -> None:
    """Set a key to a value, updating the identity-keyed inverse index."""
    if key in self:
        old_value = self[key]
        old_identity = id(old_value)
        if old_identity in self._identity_inverse:
            self._identity_inverse[old_identity].discard(key)
            if not self._identity_inverse[old_identity]:
                del self._identity_inverse[old_identity]
    super().__setitem__(key, value)
    self._identity_inverse.setdefault(id(value), set()).add(key)

__setstate__

__setstate__(state: dict[str, Any]) -> None

Restore _representative_to_key after __reduce__-driven unpickle.

Source code in src/momapy/core/mapping.py
def __setstate__(self, state: dict[str, typing.Any]) -> None:
    """Restore `_representative_to_key` after `__reduce__`-driven unpickle."""
    self._representative_to_key = SurjectionDict(state["_representative_to_key"])

add_mapping

add_mapping(layout_element: LayoutElement, model_element: ModelElement, representative: LayoutElement | None = None) -> None

Add a layout-element to model-element entry to the mapping.

The mapping is many-to-one: several layout elements may map to the same model element, so adding a new entry for a model element that is already mapped simply registers an additional layout key — existing keys are kept.

Parameters:

Name Type Description Default
layout_element LayoutElement

The layout element (or frozenset of layout elements) to use as the key.

required
model_element ModelElement

The model element to associate with the layout element.

required
representative LayoutElement | None

When layout_element is a frozenset and this argument is provided, registers representative as the representative of the frozenset key. This allows get_mapping(representative) to resolve to the model element stored under the frozenset key, even when the same element participates in other frozensets (e.g. a logical operator that is both the representative of its own gate frozenset and a participant in a modulation frozenset).

None
Source code in src/momapy/core/mapping.py
def add_mapping(
    self,
    layout_element: "LayoutElement",
    model_element: "ModelElement",
    representative: "LayoutElement | None" = None,
) -> None:
    """Add a layout-element to model-element entry to the mapping.

    The mapping is many-to-one: several layout elements may map to the
    same model element, so adding a new entry for a model element that is
    already mapped simply registers an additional layout key — existing
    keys are kept.

    Args:
        layout_element: The layout element (or frozenset of layout
            elements) to use as the key.
        model_element: The model element to associate with the layout
            element.
        representative: When ``layout_element`` is a frozenset and this argument
            is provided, registers ``representative`` as the representative of the
            frozenset key. This allows ``get_mapping(representative)`` to resolve
            to the model element stored under the frozenset key, even when
            the same element participates in other frozensets (e.g. a
            logical operator that is both the representative of its own gate
            frozenset and a participant in a modulation frozenset).
    """
    self[layout_element] = model_element
    if representative is not None:
        self._representative_to_key[representative] = layout_element

build

build(builder_to_object: dict[int, Any] | None = None) -> LayoutModelMapping

Build a frozen LayoutModelMapping from this builder.

Parameters:

Name Type Description Default
builder_to_object dict[int, Any] | None

Optional cache mapping builder id() to already-built objects, to preserve shared references.

None

Returns:

Type Description
LayoutModelMapping

A frozen LayoutModelMapping with all keys and values built

LayoutModelMapping

from their builders.

Source code in src/momapy/core/mapping.py
def build(
    self,
    builder_to_object: dict[int, typing.Any] | None = None,
) -> LayoutModelMapping:
    """Build a frozen `LayoutModelMapping` from this builder.

    Args:
        builder_to_object: Optional cache mapping builder `id()` to
            already-built objects, to preserve shared references.

    Returns:
        A frozen `LayoutModelMapping` with all keys and values built
        from their builders.
    """
    mapping = self._cls_to_build(
        {
            object_from_builder(
                key, builder_to_object=builder_to_object
            ): object_from_builder(value, builder_to_object=builder_to_object)
            for key, value in self.items()
        }
    )
    representative_to_key = FrozenSurjectionDict(
        {
            object_from_builder(
                representative, builder_to_object=builder_to_object
            ): object_from_builder(key, builder_to_object=builder_to_object)
            for representative, key in self._representative_to_key.items()
        }
    )
    object.__setattr__(mapping, "_representative_to_key", representative_to_key)
    return mapping

from_object classmethod

from_object(obj: LayoutModelMapping, object_to_builder: dict[int, Builder] | None = None) -> Self

Build a LayoutModelMappingBuilder from a frozen mapping.

Parameters:

Name Type Description Default
obj LayoutModelMapping

The frozen LayoutModelMapping to convert.

required
object_to_builder dict[int, Builder] | None

Optional cache mapping object id() to already-created builders, to preserve shared references.

None

Returns:

Type Description
Self

A LayoutModelMappingBuilder mirroring obj.

Source code in src/momapy/core/mapping.py
@classmethod
def from_object(
    cls,
    obj: LayoutModelMapping,
    object_to_builder: "dict[int, Builder] | None" = None,
) -> typing_extensions.Self:
    """Build a `LayoutModelMappingBuilder` from a frozen mapping.

    Args:
        obj: The frozen `LayoutModelMapping` to convert.
        object_to_builder: Optional cache mapping object `id()` to
            already-created builders, to preserve shared references.

    Returns:
        A `LayoutModelMappingBuilder` mirroring `obj`.
    """
    items = []
    for key, value in obj.items():
        if isinstance(key, frozenset):
            new_key = frozenset(
                [
                    builder_from_object(
                        element, object_to_builder=object_to_builder
                    )
                    for element in key
                ]
            )
        else:
            new_key = builder_from_object(key, object_to_builder=object_to_builder)
        new_value = builder_from_object(value, object_to_builder=object_to_builder)
        items.append(
            (
                new_key,
                new_value,
            )
        )
    builder = cls(items)
    representative_to_key_items = {}
    for representative, key in obj._representative_to_key.items():
        new_representative = builder_from_object(
            representative, object_to_builder=object_to_builder
        )
        if isinstance(key, frozenset):
            new_key = frozenset(
                builder_from_object(element, object_to_builder=object_to_builder)
                for element in key
            )
        else:
            new_key = builder_from_object(key, object_to_builder=object_to_builder)
        representative_to_key_items[new_representative] = new_key
    builder._representative_to_key = SurjectionDict(representative_to_key_items)
    return builder

get_child_layout_elements

get_child_layout_elements(child_model_element: ModelElement, parent_model_element: ModelElement) -> list[LayoutElement]

Return the layout elements representing child_model_element under parent_model_element.

Source code in src/momapy/core/mapping.py
def get_child_layout_elements(
    self,
    child_model_element: "ModelElement",
    parent_model_element: "ModelElement",
) -> "list[LayoutElement]":
    """Return the layout elements representing ``child_model_element`` under ``parent_model_element``."""
    child_s2 = set()
    for key in self.inverse.get(id(child_model_element), ()):
        if isinstance(key, frozenset):
            for representative in self._representative_to_key.inverse.get(key, []):
                child_s2.add(representative)
        else:
            child_s2.add(key)
    parent_s1 = set()
    for parent_layout in self.inverse.get(id(parent_model_element), ()):
        if isinstance(parent_layout, frozenset):
            parent_s1 |= parent_layout
        elif hasattr(parent_layout, "layout_elements"):
            parent_s1.update(parent_layout.layout_elements)
    return list(parent_s1 & child_s2)

get_mapping

get_mapping(map_element: MapElement) -> ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None

Return the element(s) mapped to the given map element.

If map_element is a key (a layout element or frozenset of layout elements), returns the model element it maps to. If it is a model element, returns the list of layout keys mapped to it.

Parameters:

Name Type Description Default
map_element MapElement

The layout or model element to look up.

required

Returns:

Type Description
ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None

The mapped model element, the list of mapped layout keys, or

ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None

None if the element is not in the mapping.

Source code in src/momapy/core/mapping.py
def get_mapping(
    self,
    map_element: "MapElement",
) -> "ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None":
    """Return the element(s) mapped to the given map element.

    If `map_element` is a key (a layout element or frozenset of layout
    elements), returns the model element it maps to. If it is a model
    element, returns the list of layout keys mapped to it.

    Args:
        map_element: The layout or model element to look up.

    Returns:
        The mapped model element, the list of mapped layout keys, or
        `None` if the element is not in the mapping.
    """
    if map_element in self:
        return self[map_element]
    result = self.inverse.get(id(map_element))
    if result:
        return list(result)
    return None

inverse property

inverse: frozendict

Return the value->keys inverse as a frozendict[K, frozenset].

K is the value (equality variants) or id(value) (identity variants); each bucket is a frozenset of forward keys. This is a fresh snapshot built on each access from the internally maintained index, so it is safe to read while the mapping is mutated.

Returns:

Type Description
frozendict

A frozendict mapping each value (or id(value)) to the

frozendict

frozenset of keys that map to it.

representative_to_key property

representative_to_key: SurjectionDict

Return the table mapping representatives to frozenset keys.

Map dataclass

Map(*, id_: str = make_uuid4_as_str(), model: Model | None = None, layout: Layout | None = None, layout_model_mapping: LayoutModelMapping | None = None)

Bases: MapElement

Class for maps.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'7dc128a9-ef24-431d-8e14-aaf93ca4b486'
model Model | None

The model of the map

None
layout Layout | None

The layout of the map

None
layout_model_mapping LayoutModelMapping | None

The layout model mapping of the map

None

Methods:

Name Description
get_mapping

Return the model element or layout elements mapped to map_element.

is_submap

Return True if the Map is a submap of another given map, False otherwise.

get_mapping

get_mapping(map_element: MapElement) -> ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None

Return the model element or layout elements mapped to map_element.

The lookup is bidirectional: a layout key (a singleton or frozenset) resolves to its model element, and a model element resolves to the list of layout keys mapped to it. Forwards to layout_model_mapping.get_mapping.

Returns None when the map has no layout_model_mapping (for example a layout-less map such as one read from SBML).

Source code in src/momapy/core/map.py
def get_mapping(
    self,
    map_element: "MapElement",
) -> "ModelElement | list[LayoutElement | frozenset[LayoutElement]] | None":
    """Return the model element or layout elements mapped to `map_element`.

    The lookup is bidirectional: a layout key (a singleton or frozenset)
    resolves to its model element, and a model element resolves to the
    list of layout keys mapped to it. Forwards to
    `layout_model_mapping.get_mapping`.

    Returns `None` when the map has no `layout_model_mapping` (for
    example a layout-less map such as one read from SBML).
    """
    if self.layout_model_mapping is None:
        return None
    return self.layout_model_mapping.get_mapping(map_element)

is_submap

is_submap(other: Map) -> bool

Return True if the Map is a submap of another given map, False otherwise.

A complete map is never a submap of an incomplete one: if either self or other has a None model, layout, or layout-model mapping, this returns False.

Source code in src/momapy/core/map.py
def is_submap(self, other: "Map") -> bool:
    """Return `True` if the `Map` is a submap of another given map, `False` otherwise.

    A complete map is never a submap of an incomplete one: if either `self`
    or `other` has a `None` model, layout, or layout-model mapping, this
    returns `False`.
    """
    if (
        self.model is None
        or self.layout is None
        or self.layout_model_mapping is None
        or other.model is None
        or other.layout is None
        or other.layout_model_mapping is None
    ):
        return False
    return (
        self.model.is_submodel(other.model)
        and self.layout.is_sublayout(other.layout)
        and self.layout_model_mapping.is_submapping(other.layout_model_mapping)
    )

MapElement dataclass

MapElement(*, id_: str = make_uuid4_as_str())

Base class for map elements.

Common ancestor of every model and layout element making up a map.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'acbe7894-5d8d-4d7d-a01f-121eb258e1b2'

Model dataclass

Model(*, id_: str = make_uuid4_as_str())

Bases: MapElement, ABC

Abstract base class for models.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'5ba9f8c3-462d-4ec3-9426-1176753d0cb3'

Methods:

Name Description
descendants

Return every ModelElement reachable from this Model.

is_submodel

Return whether this model is a submodel of another model.

descendants

descendants() -> list[ModelElement]

Return every ModelElement reachable from this Model.

This reflectively walks the dataclass field-graph (i.e. reference reachability) across scalar ModelElement fields and frozenset/tuple containers of the Model, deduplicating by object identity. The Model itself is not a ModelElement and is not included.

This mirrors ModelElement.descendants and contrasts with LayoutElement.descendants, which walks the explicit children() tree (visual containment) rather than reference reachability.

Returns:

Type Description
list[ModelElement]

The list of reachable ModelElement instances in visit

list[ModelElement]

order.

Source code in src/momapy/core/model.py
def descendants(self) -> list[ModelElement]:
    """Return every `ModelElement` reachable from this `Model`.

    This reflectively walks the dataclass field-graph (i.e. *reference
    reachability*) across scalar `ModelElement` fields and
    `frozenset`/`tuple` containers of the `Model`, deduplicating by
    object identity. The `Model` itself is not a `ModelElement` and is
    not included.

    This mirrors
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and contrasts with
    [`LayoutElement.descendants`][momapy.core.elements.LayoutElement.descendants],
    which walks the explicit `children()` tree (visual *containment*)
    rather than reference reachability.

    Returns:
        The list of reachable `ModelElement` instances in visit
        order.
    """
    seen: set[int] = set()
    result: list[ModelElement] = []
    for field in dataclasses.fields(type(self)):
        _walk_model_graph(getattr(self, field.name), seen, result)
    return result

is_submodel abstractmethod

is_submodel(other: Model) -> bool

Return whether this model is a submodel of another model.

Parameters:

Name Type Description Default
other Model

The model to test against.

required

Returns:

Type Description
bool

True if this model is a submodel of other.

Source code in src/momapy/core/model.py
@abc.abstractmethod
def is_submodel(self, other: "Model") -> bool:
    """Return whether this model is a submodel of another model.

    Args:
        other: The model to test against.

    Returns:
        `True` if this model is a submodel of `other`.
    """
    pass

ModelElement dataclass

ModelElement(*, id_: str = make_uuid4_as_str())

Bases: MapElement

Base class for model elements.

Common ancestor of every element carrying the semantic information of a map.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'ac9ab4ca-b2b9-4a4a-946f-db7ddf30f4c2'

Methods:

Name Description
descendants

Return every ModelElement reachable from self, excluding self.

descendants

descendants() -> list[ModelElement]

Return every ModelElement reachable from self, excluding self.

This reflectively walks the dataclass field-graph (i.e. reference reachability) across scalar ModelElement fields and frozenset/tuple containers, deduplicating by object identity. A model element referenced by several parents therefore appears once.

Note the deliberate contrast with LayoutElement.descendants, which instead walks the explicit children() tree (visual containment): there a layout element contained under two parents is reached through each, with no identity dedup.

Returns:

Type Description
list[ModelElement]

The list of reachable ModelElement instances in visit

list[ModelElement]

order, without self.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["ModelElement"]:
    """Return every `ModelElement` reachable from `self`, excluding `self`.

    This reflectively walks the dataclass field-graph (i.e. *reference
    reachability*) across scalar `ModelElement` fields and
    `frozenset`/`tuple` containers, deduplicating by object identity. A
    model element referenced by several parents therefore appears once.

    Note the deliberate contrast with
    [`LayoutElement.descendants`][momapy.core.elements.LayoutElement.descendants],
    which instead walks the explicit `children()` tree (visual
    *containment*): there a layout element contained under two parents is
    reached through each, with no identity dedup.

    Returns:
        The list of reachable `ModelElement` instances in visit
        order, without `self`.
    """
    seen: set[int] = {id(self)}
    result: list[ModelElement] = []
    if dataclasses.is_dataclass(self):
        for field in dataclasses.fields(type(self)):
            _walk_model_graph(getattr(self, field.name), seen, result)
    return result

Node dataclass

Node(*, id_: str = make_uuid4_as_str(), layout_elements: tuple[LayoutElement, ...] = tuple(), group_fill: NoneValueType | Color | None = None, group_fill_rule: FillRule | None = None, group_filter: NoneValueType | Filter | None = None, group_font_family: str | None = None, group_font_size: float | None = None, group_font_style: FontStyle | None = None, group_font_weight: FontWeight | float | None = None, group_stroke: NoneValueType | Color | None = None, group_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, group_stroke_dashoffset: NoneValueType | float | None = None, group_stroke_width: NoneValueType | float | None = None, group_text_anchor: TextAnchor | None = None, group_transform: NoneValueType | tuple[Transformation, ...] | None = None, fill: NoneValueType | Color | None = None, filter_: NoneValueType | Filter | None = None, height: float, label: TextLayout | None = None, position: Point, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, transform: NoneValueType | tuple[Transformation, ...] | None = None, width: float)

Bases: GroupLayout

Class for nodes.

A node is a group layout drawn as a shape with a position, a size, an optional label and its own border styling.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'c1f200ec-dc73-4619-87a5-f103ed893600'
layout_elements tuple[LayoutElement, ...]

The sub-layout elements of the group layout. These are part of the children of the group layout

<dynamic>
group_fill NoneValueType | Color | None

The fill color of the group layout

None
group_fill_rule FillRule | None

The fill rule of the group layout

None
group_filter NoneValueType | Filter | None

The filter of the group layout

None
group_font_family str | None

The font family of the group layout

None
group_font_size float | None

The font size of the group layout

None
group_font_style FontStyle | None

The font style of the group layout

None
group_font_weight FontWeight | float | None

The font weight of the group layout

None
group_stroke NoneValueType | Color | None

The stroke color of the group layout

None
group_stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the group layout

None
group_stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the group layout

None
group_stroke_width NoneValueType | float | None

The stroke width of the group layout

None
group_text_anchor TextAnchor | None

The text anchor of the group layout

None
group_transform NoneValueType | tuple[Transformation, ...] | None

The transform of the group layout

None
fill NoneValueType | Color | None

The fill color of the node

None
filter_ NoneValueType | Filter | None

The filter of the node

None
height float

The height of the node

required
label TextLayout | None

The label of the node

None
position Point

The position of the node

required
stroke NoneValueType | Color | None

The stroke color of the node

None
stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the node

None
stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the node

None
stroke_width NoneValueType | float | None

The stroke width of the node

None
transform NoneValueType | tuple[Transformation, ...] | None

The transform of the node

None
width float

The width of the node

required

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

angle

Return the point on the border of the node that intersects the drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

bbox

Compute and return the bounding box of the group layout element.

border

Return the point on the border of the node that intersects the drawing elements of the node with the line formed of the center anchor point of the node and the given point.

center

Return the center anchor of the node.

childless

Return a copy of the node with no children.

children

Return the children of the group layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the group layout.

east

Return the east anchor of the node.

east_north_east

Return the east north east anchor of the node.

east_south_east

Return the east south east anchor of the node.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

label_center

Return the label center anchor of the node.

north

Return the north anchor of the node.

north_east

Return the north east anchor of the node.

north_north_east

Return the north north east anchor of the node.

north_north_west

Return the north north west anchor of the node.

north_west

Return the north west anchor of the node.

own_angle

Return the point on the border of the node that intersects the self drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

own_bbox

Compute and return the bounding box of the self drawing element of the group layout.

own_border

Return the point on the border of the node that intersects the self drawing elements of the node with the line formed of the center anchor point of the node and the given point.

own_children

Return the self children of the node. A node has unique child that is its label.

own_drawing_elements

Return the node's own drawing elements.

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

size

Return the size of the node.

south

Return the south anchor of the node.

south_east

Return the south east anchor of the node.

south_south_east

Return the south south east anchor of the node.

south_south_west

Return the south south west anchor of the node.

south_west

Return the south west anchor of the node.

to_geometry

Return a list of geometry primitives from the drawing elements.

west

Return the west anchor of the node.

west_north_west

Return the west north west anchor of the node.

west_south_west

Return the west south west anchor of the node.

Attributes:

Name Type Description
x float

Return the x coordinate of the node.

y float

Return the y coordinate of the node.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

angle

angle(angle: float, unit: Literal['degrees', 'radians'] = 'degrees') -> Point | None

Return the point on the border of the node that intersects the drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

Source code in src/momapy/core/layout.py
def angle(
    self,
    angle: float,
    unit: typing.Literal["degrees", "radians"] = "degrees",
) -> Point | None:
    """Return the point on the border of the node that intersects the drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal."""
    return get_drawing_elements_angle(
        drawing_elements=self.drawing_elements(),
        angle=angle,
        unit=unit,
        center=self.center(),
    )

bbox

bbox() -> Bbox

Compute and return the bounding box of the group layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the group layout element."""
    own_bbox = self.own_bbox()
    bboxes = [child.bbox() for child in self.children()]
    min_x = own_bbox.north_west().x
    min_y = own_bbox.north_west().y
    max_x = own_bbox.south_east().x
    max_y = own_bbox.south_east().y
    for bbox in bboxes:
        if bbox.north_west().x < min_x:
            min_x = bbox.north_west().x
        if bbox.north_west().y < min_y:
            min_y = bbox.north_west().y
        if bbox.south_east().x > max_x:
            max_x = bbox.south_east().x
        if bbox.south_east().y > max_y:
            max_y = bbox.south_east().y
    bbox = Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )
    return bbox

border

border(point: Point) -> Point | None

Return the point on the border of the node that intersects the drawing elements of the node with the line formed of the center anchor point of the node and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def border(self, point: Point) -> Point | None:
    """Return the point on the border of the node that intersects the drawing elements of the node with the line formed of the center anchor point of the node and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    return get_drawing_elements_border(
        drawing_elements=self.drawing_elements(),
        point=point,
        center=self.center(),
    )

center

center() -> Point

Return the center anchor of the node.

Source code in src/momapy/core/layout.py
def center(self) -> Point:
    """Return the center anchor of the node."""
    return self.position

childless

childless() -> Self

Return a copy of the node with no children.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the node with no children."""
    return dataclasses.replace(self, label=None, layout_elements=tuple([]))

children

children() -> list[LayoutElement]

Return the children of the group layout.

These are the self children of the group layout (returned by the own_children method) and the other children of the group layout (given by the layout_elements attribute).

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the group layout.

    These are the self children of the group layout (returned by the `own_children` method) and the other children of the group layout (given by the `layout_elements` attribute).
    """
    return self.own_children() + list(self.layout_elements)

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the group layout.

The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the group layout.

    The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.
    """
    drawing_elements = self.own_drawing_elements()
    for child in self.children():
        if child is not None:
            drawing_elements += child.drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.group_fill,
        fill_rule=self.group_fill_rule,
        filter_=self.group_filter,
        font_family=self.group_font_family,
        font_size=self.group_font_size,
        font_style=self.group_font_style,
        font_weight=self.group_font_weight,
        stroke=self.group_stroke,
        stroke_dasharray=self.group_stroke_dasharray,
        stroke_dashoffset=self.group_stroke_dashoffset,
        stroke_width=self.group_stroke_width,
        text_anchor=self.group_text_anchor,
        transform=self.group_transform,
    )
    return [group]

east

east() -> Point

Return the east anchor of the node.

Source code in src/momapy/core/layout.py
def east(self) -> Point:
    """Return the east anchor of the node."""
    return self.own_angle(0)

east_north_east

east_north_east() -> Point

Return the east north east anchor of the node.

Source code in src/momapy/core/layout.py
def east_north_east(self) -> Point:
    """Return the east north east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, -self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

east_south_east

east_south_east() -> Point

Return the east south east anchor of the node.

Source code in src/momapy/core/layout.py
def east_south_east(self) -> Point:
    """Return the east south east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

label_center

label_center() -> Point

Return the label center anchor of the node.

Source code in src/momapy/core/layout.py
def label_center(self) -> Point:
    """Return the label center anchor of the node."""
    return self.position

north

north() -> Point

Return the north anchor of the node.

Source code in src/momapy/core/layout.py
def north(self) -> Point:
    """Return the north anchor of the node."""
    return self.own_angle(90)

north_east

north_east() -> Point

Return the north east anchor of the node.

Source code in src/momapy/core/layout.py
def north_east(self) -> Point:
    """Return the north east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, -self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

north_north_east

north_north_east() -> Point

Return the north north east anchor of the node.

Source code in src/momapy/core/layout.py
def north_north_east(self) -> Point:
    """Return the north north east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 4, -self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

north_north_west

north_north_west() -> Point

Return the north north west anchor of the node.

Source code in src/momapy/core/layout.py
def north_north_west(self) -> Point:
    """Return the north north west anchor of the node."""
    line = Line(self.center(), self.center() - (self.width / 4, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

north_west

north_west() -> Point

Return the north west anchor of the node.

Source code in src/momapy/core/layout.py
def north_west(self) -> Point:
    """Return the north west anchor of the node."""
    line = Line(self.center(), self.center() - (self.width / 2, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

own_angle

own_angle(angle: float, unit: Literal['degrees', 'radians'] = 'degrees') -> Point | None

Return the point on the border of the node that intersects the self drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal.

Source code in src/momapy/core/layout.py
def own_angle(
    self,
    angle: float,
    unit: typing.Literal["degrees", "radians"] = "degrees",
) -> Point | None:
    """Return the point on the border of the node that intersects the self drawing elements of the node with the line passing through the center anchor point of the node and at a given angle from the horizontal."""
    return get_drawing_elements_angle(
        drawing_elements=self.own_drawing_elements(),
        angle=angle,
        unit=unit,
        center=self.center(),
    )

own_bbox

own_bbox() -> Bbox

Compute and return the bounding box of the self drawing element of the group layout.

Source code in src/momapy/core/layout.py
def own_bbox(self) -> Bbox:
    """Compute and return the bounding box of the self drawing element of the group layout."""
    primitives = self.own_to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

own_border

own_border(point: Point) -> Point | None

Return the point on the border of the node that intersects the self drawing elements of the node with the line formed of the center anchor point of the node and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def own_border(self, point: Point) -> Point | None:
    """Return the point on the border of the node that intersects the self drawing elements of the node with the line formed of the center anchor point of the node and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    return get_drawing_elements_border(
        drawing_elements=self.own_drawing_elements(),
        point=point,
        center=self.center(),
    )

own_children

own_children() -> list[LayoutElement]

Return the self children of the node. A node has unique child that is its label.

Source code in src/momapy/core/layout.py
def own_children(self) -> list[LayoutElement]:
    """Return the self children of the node. A node has unique child that is its label."""
    if self.label is not None:
        return [self.label]
    return []

own_drawing_elements

own_drawing_elements() -> list[DrawingElement]

Return the node's own drawing elements.

Source code in src/momapy/core/layout.py
def own_drawing_elements(self) -> list[DrawingElement]:
    """Return the node's own drawing elements."""
    drawing_elements = self._border_drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}_own",
        elements=tuple(drawing_elements),
        fill=self.fill,
        filter_=self.filter_,
        id_=f"{self.id_}_own",
        stroke=self.stroke,
        stroke_dasharray=self.stroke_dasharray,
        stroke_dashoffset=self.stroke_dashoffset,
        stroke_width=self.stroke_width,
        transform=self.transform,
    )
    return [group]

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

Source code in src/momapy/core/layout.py
def own_to_geometry(
    self,
) -> list[
    Segment | QuadraticBezierCurve | CubicBezierCurve | GeometryEllipticalArc
]:
    """Return a list of geometry primitives from the self drawing elements."""
    return drawing_elements_to_geometry(self.own_drawing_elements())

size

size() -> tuple[float, float]

Return the size of the node.

Source code in src/momapy/core/layout.py
def size(self) -> tuple[float, float]:
    """Return the size of the node."""
    return (self.width, self.height)

south

south() -> Point

Return the south anchor of the node.

Source code in src/momapy/core/layout.py
def south(self) -> Point:
    """Return the south anchor of the node."""
    return self.own_angle(270)

south_east

south_east() -> Point

Return the south east anchor of the node.

Source code in src/momapy/core/layout.py
def south_east(self) -> Point:
    """Return the south east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 2, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

south_south_east

south_south_east() -> Point

Return the south south east anchor of the node.

Source code in src/momapy/core/layout.py
def south_south_east(self) -> Point:
    """Return the south south east anchor of the node."""
    line = Line(self.center(), self.center() + (self.width / 4, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

south_south_west

south_south_west() -> Point

Return the south south west anchor of the node.

Source code in src/momapy/core/layout.py
def south_south_west(self) -> Point:
    """Return the south south west anchor of the node."""
    line = Line(self.center(), self.center() + (-self.width / 4, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

south_west

south_west() -> Point

Return the south west anchor of the node.

Source code in src/momapy/core/layout.py
def south_west(self) -> Point:
    """Return the south west anchor of the node."""
    line = Line(self.center(), self.center() + (-self.width / 2, self.height / 2))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

west

west() -> Point

Return the west anchor of the node.

Source code in src/momapy/core/layout.py
def west(self) -> Point:
    """Return the west anchor of the node."""
    return self.own_angle(180)

west_north_west

west_north_west() -> Point

Return the west north west anchor of the node.

Source code in src/momapy/core/layout.py
def west_north_west(self) -> Point:
    """Return the west north west anchor of the node."""
    line = Line(self.center(), self.center() - (self.width / 2, self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

west_south_west

west_south_west() -> Point

Return the west south west anchor of the node.

Source code in src/momapy/core/layout.py
def west_south_west(self) -> Point:
    """Return the west south west anchor of the node."""
    line = Line(self.center(), self.center() + (-self.width / 2, self.height / 4))
    angle = -line.get_angle_to_horizontal()
    return self.own_angle(angle, unit="radians")

x property

x: float

Return the x coordinate of the node.

y property

y: float

Return the y coordinate of the node.

Orientation

Bases: Enum

Orientation along an axis.

Either horizontal or vertical. For a cardinal direction (up, right, down, left), see Direction.

Shape dataclass

Shape(*, id_: str = make_uuid4_as_str())

Bases: LayoutElement

Class for basic shapes.

A shape is the most simple layout element and has no children.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'220802c6-707c-4844-9648-a72b4f0dc1bf'

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

bbox

Compute and return the bounding box of the shape.

childless

Return a copy of the shape with no children.

children

Return the children of the shape.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the layout element.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

to_geometry

Return a list of geometry primitives from the drawing elements.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

bbox

bbox() -> Bbox

Compute and return the bounding box of the shape.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the shape."""
    primitives = self.to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

childless

childless() -> Self

Return a copy of the shape with no children.

A shape has no children, so return a copy of the shape.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the shape with no children.

    A shape has no children, so return a copy of the shape.
    """
    return copy.deepcopy(self)

children

children() -> list[LayoutElement]

Return the children of the shape.

A shape has no children, so return an empty list.

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the shape.

    A shape has no children, so return an empty list.
    """
    return []

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements abstractmethod

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the layout element.

Source code in src/momapy/core/elements.py
@abc.abstractmethod
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the layout element."""
    pass

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

SingleHeadedArc dataclass

SingleHeadedArc(*, id_: str = make_uuid4_as_str(), layout_elements: tuple[LayoutElement, ...] = tuple(), group_fill: NoneValueType | Color | None = None, group_fill_rule: FillRule | None = None, group_filter: NoneValueType | Filter | None = None, group_font_family: str | None = None, group_font_size: float | None = None, group_font_style: FontStyle | None = None, group_font_weight: FontWeight | float | None = None, group_stroke: NoneValueType | Color | None = None, group_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, group_stroke_dashoffset: NoneValueType | float | None = None, group_stroke_width: NoneValueType | float | None = None, group_text_anchor: TextAnchor | None = None, group_transform: NoneValueType | tuple[Transformation, ...] | None = None, end_shorten: float = 0.0, fill: NoneValueType | Color | None = None, filter_: NoneValueType | Filter | None = None, path_fill: NoneValueType | Color | None = None, path_filter: NoneValueType | Filter | None = None, path_stroke: NoneValueType | Color | None = None, path_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, path_stroke_dashoffset: NoneValueType | float | None = None, path_stroke_width: float | None = None, path_transform: NoneValueType | tuple[Transformation, ...] | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, segments: tuple[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc, ...] = tuple(), source: LayoutElement | None = None, start_shorten: float = 0.0, target: LayoutElement | None = None, transform: NoneValueType | tuple[Transformation, ...] | None = None, arrowhead_fill: NoneValueType | Color | None = None, arrowhead_filter: NoneValueType | Filter | None = None, arrowhead_stroke: NoneValueType | Color | None = None, arrowhead_stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, arrowhead_stroke_dashoffset: NoneValueType | float | None = None, arrowhead_stroke_width: NoneValueType | float | None = None, arrowhead_transform: NoneValueType | tuple[Transformation, ...] | None = None)

Bases: Arc

Base class for single-headed arcs.

A single-headed arc is formed of a path and a unique arrowhead at its end.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'2db4dead-a8ef-44f5-a885-8d34d1070ab5'
layout_elements tuple[LayoutElement, ...]

The sub-layout elements of the group layout. These are part of the children of the group layout

<dynamic>
group_fill NoneValueType | Color | None

The fill color of the group layout

None
group_fill_rule FillRule | None

The fill rule of the group layout

None
group_filter NoneValueType | Filter | None

The filter of the group layout

None
group_font_family str | None

The font family of the group layout

None
group_font_size float | None

The font size of the group layout

None
group_font_style FontStyle | None

The font style of the group layout

None
group_font_weight FontWeight | float | None

The font weight of the group layout

None
group_stroke NoneValueType | Color | None

The stroke color of the group layout

None
group_stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the group layout

None
group_stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the group layout

None
group_stroke_width NoneValueType | float | None

The stroke width of the group layout

None
group_text_anchor TextAnchor | None

The text anchor of the group layout

None
group_transform NoneValueType | tuple[Transformation, ...] | None

The transform of the group layout

None
end_shorten float

The length the end of the arc will be shorten by

0.0
fill NoneValueType | Color | None

The fill color of the arc

None
filter_ NoneValueType | Filter | None

The filter of the arc

None
path_fill NoneValueType | Color | None

The path fill color of the arc

None
path_filter NoneValueType | Filter | None

The path filter of the arc

None
path_stroke NoneValueType | Color | None

The path stroke color of the arc

None
path_stroke_dasharray NoneValueType | tuple[float, ...] | None

The path stroke dasharray of the arc

None
path_stroke_dashoffset NoneValueType | float | None

The path stroke dashoffset of the arc

None
path_stroke_width float | None

The path stroke width of the arc

None
path_transform NoneValueType | tuple[Transformation, ...] | None

The path transform of the arc

None
stroke NoneValueType | Color | None

The stroke color of the arc

None
stroke_dasharray NoneValueType | tuple[float, ...] | None

The stroke dasharray of the arc

None
stroke_dashoffset NoneValueType | float | None

The stroke dashoffset of the arc

None
stroke_width NoneValueType | float | None

The stroke width of the arc

None
segments tuple[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc, ...]

The path segments of the arc

<dynamic>
source LayoutElement | None

The source of the arc

None
start_shorten float

The length the start of the arc will be shorten by

0.0
target LayoutElement | None

The target of the arc

None
transform NoneValueType | tuple[Transformation, ...] | None

The transform of the arc

None
arrowhead_fill NoneValueType | Color | None

The arrowhead fill color of the arc

None
arrowhead_filter NoneValueType | Filter | None

The arrowhead filter of the arc

None
arrowhead_stroke NoneValueType | Color | None

The arrowhead stroke color of the arc

None
arrowhead_stroke_dasharray NoneValueType | tuple[float, ...] | None

The arrowhead stroke dasharray of the arc

None
arrowhead_stroke_dashoffset NoneValueType | float | None

The arrowhead stroke dashoffset of the arc

None
arrowhead_stroke_width NoneValueType | float | None

The arrowhead stroke width of the arc

None
arrowhead_transform NoneValueType | tuple[Transformation, ...] | None

The arrowhead transform of the arc

None

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

arrowhead_base

Return the arrowhead base anchor point of the single-headed arc.

arrowhead_bbox

Return the bounding box of the single-headed arc arrowhead.

arrowhead_border

Return the point at the intersection of the drawing elements of the single-headed arc arrowhead and the line going through the center of these drawing elements and the given point.

arrowhead_drawing_elements

Return the drawing elements of the single-headed arc arrowhead.

arrowhead_length

Return the length of the single-headed arc arrowhead.

arrowhead_tip

Return the arrowhead tip anchor point of the single-headed arc.

bbox

Compute and return the bounding box of the group layout element.

childless

Return a copy of the arc with no children.

children

Return the children of the group layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the group layout.

end_point

Return the ending point of the arc.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

fraction

Return the position and angle on the arc at a given fraction (of the total arc length).

length

Return the total length of the arc path.

own_bbox

Compute and return the bounding box of the self drawing element of the group layout.

own_children

Return the self children of the arc.

own_drawing_elements

Return the self drawing elements of the single-headed arc.

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

path_drawing_elements

Return the drawing elements of the single-headed arc path.

points

Return the points of the arc path.

start_point

Return the starting point of the arc.

to_geometry

Return a list of geometry primitives from the drawing elements.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

arrowhead_base

arrowhead_base() -> Point

Return the arrowhead base anchor point of the single-headed arc.

Source code in src/momapy/core/layout.py
def arrowhead_base(self) -> Point:
    """Return the arrowhead base anchor point of the single-headed arc."""
    arrowhead_length = self.arrowhead_length()
    segment = self.segments[-1]
    segment_length = segment.length()
    if segment_length == 0:
        return self.arrowhead_tip() - (arrowhead_length, 0)
    fraction = 1 - (arrowhead_length + self.end_shorten) / segment_length
    return segment.get_position_at_fraction(fraction)

arrowhead_bbox

arrowhead_bbox() -> Bbox

Return the bounding box of the single-headed arc arrowhead.

Source code in src/momapy/core/layout.py
def arrowhead_bbox(self) -> Bbox:
    """Return the bounding box of the single-headed arc arrowhead."""
    return get_drawing_elements_bbox(self.arrowhead_drawing_elements())

arrowhead_border

arrowhead_border(point: Point) -> Point

Return the point at the intersection of the drawing elements of the single-headed arc arrowhead and the line going through the center of these drawing elements and the given point.

When there are multiple intersection points, the one closest to the given point is returned.

Source code in src/momapy/core/layout.py
def arrowhead_border(self, point: Point) -> Point:
    """Return the point at the intersection of the drawing elements of the single-headed arc arrowhead and the line going through the center of these drawing elements and the given point.

    When there are multiple intersection points, the one closest to the given point is returned.
    """
    point = get_drawing_elements_border(self.arrowhead_drawing_elements(), point)
    if point is None:
        return self.arrowhead_tip()
    return point

arrowhead_drawing_elements

arrowhead_drawing_elements() -> list[DrawingElement]

Return the drawing elements of the single-headed arc arrowhead.

Source code in src/momapy/core/layout.py
def arrowhead_drawing_elements(
    self,
) -> list[DrawingElement]:
    """Return the drawing elements of the single-headed arc arrowhead."""
    drawing_elements = self._arrowhead_border_drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}_arrowhead",
        elements=tuple(drawing_elements),
        fill=self.arrowhead_fill,
        filter_=self.arrowhead_filter,
        id_=f"{self.id_}_arrowhead",
        stroke=self.arrowhead_stroke,
        stroke_dasharray=self.arrowhead_stroke_dasharray,
        stroke_dashoffset=self.arrowhead_stroke_dashoffset,
        stroke_width=self.arrowhead_stroke_width,
        transform=self.arrowhead_transform,
    )
    transformation = self._get_arrowhead_transformation()
    group = group.transformed(transformation)
    return [group]

arrowhead_length

arrowhead_length() -> float

Return the length of the single-headed arc arrowhead.

Source code in src/momapy/core/layout.py
def arrowhead_length(self) -> float:
    """Return the length of the single-headed arc arrowhead."""
    bbox = get_drawing_elements_bbox(self._arrowhead_border_drawing_elements())
    if math.isnan(bbox.width):
        return 0.0
    return bbox.east().x

arrowhead_tip

arrowhead_tip() -> Point

Return the arrowhead tip anchor point of the single-headed arc.

Source code in src/momapy/core/layout.py
def arrowhead_tip(self) -> Point:
    """Return the arrowhead tip anchor point of the single-headed arc."""
    segment = self.segments[-1]
    segment_length = segment.length()
    if segment_length == 0:
        return segment.p2
    fraction = 1 - self.end_shorten / segment_length
    return segment.get_position_at_fraction(fraction)

bbox

bbox() -> Bbox

Compute and return the bounding box of the group layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the group layout element."""
    own_bbox = self.own_bbox()
    bboxes = [child.bbox() for child in self.children()]
    min_x = own_bbox.north_west().x
    min_y = own_bbox.north_west().y
    max_x = own_bbox.south_east().x
    max_y = own_bbox.south_east().y
    for bbox in bboxes:
        if bbox.north_west().x < min_x:
            min_x = bbox.north_west().x
        if bbox.north_west().y < min_y:
            min_y = bbox.north_west().y
        if bbox.south_east().x > max_x:
            max_x = bbox.south_east().x
        if bbox.south_east().y > max_y:
            max_y = bbox.south_east().y
    bbox = Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )
    return bbox

childless

childless() -> Self

Return a copy of the arc with no children.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the arc with no children."""
    return dataclasses.replace(self, layout_elements=tuple([]))

children

children() -> list[LayoutElement]

Return the children of the group layout.

These are the self children of the group layout (returned by the own_children method) and the other children of the group layout (given by the layout_elements attribute).

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the group layout.

    These are the self children of the group layout (returned by the `own_children` method) and the other children of the group layout (given by the `layout_elements` attribute).
    """
    return self.own_children() + list(self.layout_elements)

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the group layout.

The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the group layout.

    The returned drawing elements are a group drawing element formed of the self drawing elements of the group layout and the drawing elements of its children.
    """
    drawing_elements = self.own_drawing_elements()
    for child in self.children():
        if child is not None:
            drawing_elements += child.drawing_elements()
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.group_fill,
        fill_rule=self.group_fill_rule,
        filter_=self.group_filter,
        font_family=self.group_font_family,
        font_size=self.group_font_size,
        font_style=self.group_font_style,
        font_weight=self.group_font_weight,
        stroke=self.group_stroke,
        stroke_dasharray=self.group_stroke_dasharray,
        stroke_dashoffset=self.group_stroke_dashoffset,
        stroke_width=self.group_stroke_width,
        text_anchor=self.group_text_anchor,
        transform=self.group_transform,
    )
    return [group]

end_point

end_point() -> Point

Return the ending point of the arc.

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def end_point(self) -> Point:
    """Return the ending point of the arc.

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    return self.points()[-1]

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

fraction

fraction(fraction: float) -> tuple[Point, float]

Return the position and angle on the arc at a given fraction (of the total arc length).

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def fraction(self, fraction: float) -> tuple[Point, float]:
    """Return the position and angle on the arc at a given fraction (of the total arc length).

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    current_length = 0
    length_to_reach = fraction * self.length()
    for segment in self.segments:
        current_length += segment.length()
        if current_length >= length_to_reach:
            break
    segment_start_length = current_length - segment.length()
    segment_fraction = (length_to_reach - segment_start_length) / segment.length()
    position, angle = segment.get_position_and_angle_at_fraction(segment_fraction)
    return position, angle

length

length() -> float

Return the total length of the arc path.

Source code in src/momapy/core/layout.py
def length(self) -> float:
    """Return the total length of the arc path."""
    return sum([segment.length() for segment in self.segments])

own_bbox

own_bbox() -> Bbox

Compute and return the bounding box of the self drawing element of the group layout.

Source code in src/momapy/core/layout.py
def own_bbox(self) -> Bbox:
    """Compute and return the bounding box of the self drawing element of the group layout."""
    primitives = self.own_to_geometry()
    if not primitives:
        return Bbox(Point(0.0, 0.0), 0, 0)
    bboxes = [p.bbox() for p in primitives]
    return Bbox.union(bboxes)

own_children

own_children() -> list[LayoutElement]

Return the self children of the arc.

Source code in src/momapy/core/layout.py
def own_children(self) -> list[LayoutElement]:
    """Return the self children of the arc."""
    return []

own_drawing_elements

own_drawing_elements() -> list[DrawingElement]

Return the self drawing elements of the single-headed arc.

Source code in src/momapy/core/layout.py
def own_drawing_elements(self) -> list[DrawingElement]:
    """Return the self drawing elements of the single-headed arc."""
    drawing_elements = (
        self.path_drawing_elements() + self.arrowhead_drawing_elements()
    )
    group = Group(
        class_=f"{type(self).__name__}_own",
        elements=tuple(drawing_elements),
        fill=self.fill,
        filter_=self.filter_,
        id_=f"{self.id_}_own",
        stroke=self.stroke,
        stroke_dasharray=self.stroke_dasharray,
        stroke_dashoffset=self.stroke_dashoffset,
        stroke_width=self.stroke_width,
        transform=self.transform,
    )
    return [group]

own_to_geometry

Return a list of geometry primitives from the self drawing elements.

Source code in src/momapy/core/layout.py
def own_to_geometry(
    self,
) -> list[
    Segment | QuadraticBezierCurve | CubicBezierCurve | GeometryEllipticalArc
]:
    """Return a list of geometry primitives from the self drawing elements."""
    return drawing_elements_to_geometry(self.own_drawing_elements())

path_drawing_elements

path_drawing_elements() -> list[Path]

Return the drawing elements of the single-headed arc path.

Source code in src/momapy/core/layout.py
def path_drawing_elements(self) -> list[Path]:
    """Return the drawing elements of the single-headed arc path."""
    arrowhead_length = self.arrowhead_length()
    if len(self.segments) == 1:
        segment = (
            self.segments[0]
            .shortened(self.start_shorten, "start")
            .shortened(self.end_shorten + arrowhead_length, "end")
        )
        actions = [
            MoveTo(segment.p1),
            self._make_path_action_from_segment(segment),
        ]
    else:
        first_segment = self.segments[0].shortened(self.start_shorten, "start")
        last_segment = self.segments[-1].shortened(
            self.end_shorten + arrowhead_length, "end"
        )
        actions = [
            MoveTo(first_segment.p1),
            self._make_path_action_from_segment(first_segment),
        ]
        for segment in self.segments[1:-1]:
            action = self._make_path_action_from_segment(segment)
            actions.append(action)
        actions.append(self._make_path_action_from_segment(last_segment))
    path = Path(
        actions=tuple(actions),
        class_=f"{type(self).__name__}_path",
        fill=self.path_fill,
        filter_=self.path_filter,
        id_=f"{self.id_}_path",
        stroke=self.path_stroke,
        stroke_dasharray=self.path_stroke_dasharray,
        stroke_dashoffset=self.path_stroke_dashoffset,
        stroke_width=self.path_stroke_width,
        transform=self.path_transform,
    )
    return [path]

points

points() -> list[Point]

Return the points of the arc path.

An arc with no segments has no points and returns an empty list.

Source code in src/momapy/core/layout.py
def points(self) -> list[Point]:
    """Return the points of the arc path.

    An arc with no segments has no points and returns an empty list.
    """
    if not self.segments:
        return []
    points = []
    for segment in self.segments:
        points.append(segment.p1)
    points.append(segment.p2)
    return points

start_point

start_point() -> Point

Return the starting point of the arc.

Raises:

Type Description
ValueError

If the arc has no segments.

Source code in src/momapy/core/layout.py
def start_point(self) -> Point:
    """Return the starting point of the arc.

    Raises:
        ValueError: If the arc has no segments.
    """
    if not self.segments:
        raise ValueError("arc has no segments")
    return self.points()[0]

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

TextLayout dataclass

TextLayout(*, id_: str = make_uuid4_as_str(), text: str, font_family: str = get_initial_value('font_family'), font_size: float = get_initial_value('font_size'), font_style: FontStyle = get_initial_value('font_style'), font_weight: FontWeight | int = get_initial_value('font_weight'), position: Point, width: float | None = None, height: float | None = None, horizontal_alignment: HAlignment = LEFT, vertical_alignment: VAlignment = TOP, justify: bool = False, fill: NoneValueType | Color | None = None, filter_: NoneValueType | Filter | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation, ...] | None = None)

Bases: LayoutElement

Class for text layouts.

A text layout draws a piece of text at a position with its own font and styling.

Parameters:

Name Type Description Default
id_ str

The id of the map element. This id is purely for the user to keep track of the element, it does not need to be unique and is not part of the identity of the element, i.e., it is not considered when testing for equality between two map elements or when hashing the map element

'd87e7b10-b371-472e-8cd6-c403fca3578a'
text str

The text of the text layout

required
font_family str

The font family of the text layout

'DejaVu Sans'
font_size float

The font size of the text layout

16.0
font_style FontStyle

The font style of the text layout

<FontStyle.NORMAL: 0>
font_weight FontWeight | int

The font weight of the text layout

<FontWeight.NORMAL: 0>
position Point

The position of the text layout

required
width float | None

The width of the text layout

None
height float | None

The height of the text layout

None
horizontal_alignment HAlignment

The horizontal alignment of the text layout

<HAlignment.LEFT: 1>
vertical_alignment VAlignment

The vertical alignment of the text layout

<VAlignment.TOP: 1>
justify bool

Whether to justify the text or not

False
fill NoneValueType | Color | None

The text fill color of the text layout

None
filter_ NoneValueType | Filter | None

The filter of the text layout

None
stroke NoneValueType | Color | None

The text stroke color of the text layout

None
stroke_dasharray NoneValueType | tuple[float, ...] | None

The text stroke dasharray of the text layout

None
stroke_dashoffset NoneValueType | float | None

The text stroke dashoffset of the text layout

None
stroke_width float | None

The text stroke width of the text layout

None
text_anchor TextAnchor | None

The text anchor of the text layout

None
transform NoneValueType | tuple[Transformation, ...] | None

The transform of the text layout

None

Methods:

Name Description
anchor_point

Return an anchor point of the layout element.

bbox

Compute and return the bounding box of the layout element.

childless

Return a copy of the text layout with no children.

children

Return the children of the text layout.

contains

Return True if another layout element is a descendant of the layout element, False otherwise.

descendants

Return the descendants of the layout element.

drawing_elements

Return the drawing elements of the text layout.

east

Return the east anchor of the text layout.

east_north_east

Return the east north east anchor of the text layout.

east_south_east

Return the east south east anchor of the text layout.

equals

Return True if the layout element is equal to another layout element, False otherwise.

flattened

Return a list containing copy of the layout element with no children and all its descendants with no children.

north

Return the north anchor of the text layout.

north_east

Return the north east anchor of the text layout.

north_north_east

Return the north north east anchor of the text layout.

north_north_west

Return the north north west anchor of the text layout.

north_west

Return the north west anchor of the text layout.

south

Return the south anchor of the text layout.

south_east

Return the south east anchor of the text layout.

south_south_east

Return the south south east anchor of the text layout.

south_south_west

Return the south south west anchor of the text layout.

south_west

Return the south west anchor of the text layout.

to_geometry

Return a list of geometry primitives from the drawing elements.

west

Return the west anchor of the text layout.

west_north_west

Return the west north west anchor of the text layout.

west_south_west

Return the west south west anchor of the text layout.

Attributes:

Name Type Description
x float

Return the x coordinate of the text layout.

y float

Return the y coordinate of the text layout.

anchor_point

anchor_point(anchor_name: str) -> Point

Return an anchor point of the layout element.

Source code in src/momapy/core/elements.py
def anchor_point(self, anchor_name: str) -> Point:
    """Return an anchor point of the layout element."""
    return getattr(self, anchor_name)()

bbox

bbox() -> Bbox

Compute and return the bounding box of the layout element.

Source code in src/momapy/core/layout.py
def bbox(self) -> Bbox:
    """Compute and return the bounding box of the layout element."""
    line_positions = self._get_line_positions()
    font_file_path = self._get_font_file_path(
        self.font_family, self.font_weight, self.font_style
    )
    font = self._make_font(font_file_path, self.font_size)
    font_ascent, font_descent, _ = self._get_font_parameters(font)
    line, position, line_width = line_positions[0]
    min_x = position.x
    max_x = min_x + line_width
    min_y = position.y - font_ascent
    max_y = position.y + font_descent
    for line, position, line_width in line_positions[1:]:
        start_x = position.x
        if start_x < min_x:
            min_x = start_x
        end_x = start_x + line_width
        if end_x > max_x:
            max_x = end_x
        max_y = position.y + font_descent
    return Bbox(
        Point(min_x / 2 + max_x / 2, min_y / 2 + max_y / 2),
        max_x - min_x,
        max_y - min_y,
    )

childless

childless() -> Self

Return a copy of the text layout with no children.

The text layout has no children, so return a copy of the text layout.

Source code in src/momapy/core/layout.py
def childless(self) -> typing_extensions.Self:
    """Return a copy of the text layout with no children.

    The text layout has no children, so return a copy of the text layout.
    """
    return copy.deepcopy(self)

children

children() -> list[LayoutElement]

Return the children of the text layout.

The text layout has no children, so return an empty list.

Source code in src/momapy/core/layout.py
def children(self) -> list[LayoutElement]:
    """Return the children of the text layout.

    The text layout has no children, so return an empty list.
    """
    return []

contains

contains(other: LayoutElement) -> bool

Return True if another layout element is a descendant of the layout element, False otherwise.

Source code in src/momapy/core/elements.py
def contains(self, other: "LayoutElement") -> bool:
    """Return `True` if another layout element is a descendant of the layout element, `False` otherwise."""
    return other in self.descendants()

descendants

descendants() -> list[LayoutElement]

Return the descendants of the layout element.

This walks the explicit children() tree (i.e. visual containment) depth-first, returning every layout element in the contained subtree (without self).

Note the deliberate contrast with ModelElement.descendants and Model.descendants, which reflectively walk the dataclass field-graph (i.e. reference reachability) and deduplicate by object identity. A model element referenced by several parents therefore appears once across the model graph, whereas layout descendants are strictly the contained subtree and a layout element contained under two parents is reached through each.

Returns:

Type Description
list[LayoutElement]

The list of descendant layout elements in visit order.

Source code in src/momapy/core/elements.py
def descendants(self) -> list["LayoutElement"]:
    """Return the descendants of the layout element.

    This walks the explicit `children()` tree (i.e. visual
    *containment*) depth-first, returning every layout element in the
    contained subtree (without `self`).

    Note the deliberate contrast with
    [`ModelElement.descendants`][momapy.core.elements.ModelElement.descendants]
    and [`Model.descendants`][momapy.core.model.Model.descendants],
    which reflectively walk the dataclass field-graph (i.e. *reference
    reachability*) and deduplicate by object identity. A model element
    referenced by several parents therefore appears once across the
    model graph, whereas layout descendants are strictly the contained
    subtree and a layout element contained under two parents is reached
    through each.

    Returns:
        The list of descendant layout elements in visit order.
    """
    descendants = []
    for child in self.children():
        descendants.append(child)
        descendants += child.descendants()
    return descendants

drawing_elements

drawing_elements() -> list[DrawingElement]

Return the drawing elements of the text layout.

Source code in src/momapy/core/layout.py
def drawing_elements(self) -> list[DrawingElement]:
    """Return the drawing elements of the text layout."""
    drawing_elements = []
    lines_positions = self._get_line_positions()
    for line, position, _ in lines_positions:
        text = Text(
            text=line,
            point=position,
        )
        drawing_elements.append(text)
    group = Group(
        class_=f"{type(self).__name__}",
        elements=tuple(drawing_elements),
        id_=f"{self.id_}",
        fill=self.fill,
        filter_=self.filter_,
        font_family=self.font_family,
        font_size=self.font_size,
        font_style=self.font_style,
        font_weight=self.font_weight,
        stroke=self.stroke,
        stroke_dasharray=self.stroke_dasharray,
        stroke_dashoffset=self.stroke_dashoffset,
        stroke_width=self.stroke_width,
        text_anchor=self.text_anchor,
        transform=self.transform,
    )
    return [group]

east

east() -> Point

Return the east anchor of the text layout.

Source code in src/momapy/core/layout.py
def east(self) -> Point:
    """Return the east anchor of the text layout."""
    return self.bbox().east()

east_north_east

east_north_east() -> Point

Return the east north east anchor of the text layout.

Source code in src/momapy/core/layout.py
def east_north_east(self) -> Point:
    """Return the east north east anchor of the text layout."""
    return self.bbox().east_north_east()

east_south_east

east_south_east() -> Point

Return the east south east anchor of the text layout.

Source code in src/momapy/core/layout.py
def east_south_east(self) -> Point:
    """Return the east south east anchor of the text layout."""
    return self.bbox().east_south_east()

equals

equals(other: LayoutElement, flattened: bool = False, unordered: bool = False) -> bool

Return True if the layout element is equal to another layout element, False otherwise.

Source code in src/momapy/core/elements.py
def equals(
    self, other: "LayoutElement", flattened: bool = False, unordered: bool = False
) -> bool:
    """Return `True` if the layout element is equal to another layout element, `False` otherwise."""
    if type(self) is type(other):
        if not flattened:
            return self == other
        else:
            if not unordered:
                return self.flattened() == other.flattened()
            else:
                return set(self.flattened()) == set(other.flattened())
    return False

flattened

flattened() -> list[LayoutElement]

Return a list containing copy of the layout element with no children and all its descendants with no children.

Source code in src/momapy/core/elements.py
def flattened(self) -> list["LayoutElement"]:
    """Return a list containing copy of the layout element with no children and all its descendants with no children."""
    flattened = [self.childless()]
    for child in self.children():
        flattened += child.flattened()
    return flattened

north

north() -> Point

Return the north anchor of the text layout.

Source code in src/momapy/core/layout.py
def north(self) -> Point:
    """Return the north anchor of the text layout."""
    return self.bbox().north()

north_east

north_east() -> Point

Return the north east anchor of the text layout.

Source code in src/momapy/core/layout.py
def north_east(self) -> Point:
    """Return the north east anchor of the text layout."""
    return self.bbox().north_east()

north_north_east

north_north_east() -> Point

Return the north north east anchor of the text layout.

Source code in src/momapy/core/layout.py
def north_north_east(self) -> Point:
    """Return the north north east anchor of the text layout."""
    return self.bbox().north_north_east()

north_north_west

north_north_west() -> Point

Return the north north west anchor of the text layout.

Source code in src/momapy/core/layout.py
def north_north_west(self) -> Point:
    """Return the north north west anchor of the text layout."""
    return self.bbox().north_north_west()

north_west

north_west() -> Point

Return the north west anchor of the text layout.

Source code in src/momapy/core/layout.py
def north_west(self) -> Point:
    """Return the north west anchor of the text layout."""
    return self.bbox().north_west()

south

south() -> Point

Return the south anchor of the text layout.

Source code in src/momapy/core/layout.py
def south(self) -> Point:
    """Return the south anchor of the text layout."""
    return self.bbox().south()

south_east

south_east() -> Point

Return the south east anchor of the text layout.

Source code in src/momapy/core/layout.py
def south_east(self) -> Point:
    """Return the south east anchor of the text layout."""
    return self.bbox().south_east()

south_south_east

south_south_east() -> Point

Return the south south east anchor of the text layout.

Source code in src/momapy/core/layout.py
def south_south_east(self) -> Point:
    """Return the south south east anchor of the text layout."""
    return self.bbox().south_south_east()

south_south_west

south_south_west() -> Point

Return the south south west anchor of the text layout.

Source code in src/momapy/core/layout.py
def south_south_west(self) -> Point:
    """Return the south south west anchor of the text layout."""
    return self.bbox().south_south_west()

south_west

south_west() -> Point

Return the south west anchor of the text layout.

Source code in src/momapy/core/layout.py
def south_west(self) -> Point:
    """Return the south west anchor of the text layout."""
    return self.bbox().south_west()

to_geometry

Return a list of geometry primitives from the drawing elements.

Source code in src/momapy/core/elements.py
def to_geometry(
    self,
) -> list[Segment | QuadraticBezierCurve | CubicBezierCurve | EllipticalArc]:
    """Return a list of geometry primitives from the drawing elements."""
    return drawing_elements_to_geometry(self.drawing_elements())

west

west() -> Point

Return the west anchor of the text layout.

Source code in src/momapy/core/layout.py
def west(self) -> Point:
    """Return the west anchor of the text layout."""
    return self.bbox().west()

west_north_west

west_north_west() -> Point

Return the west north west anchor of the text layout.

Source code in src/momapy/core/layout.py
def west_north_west(self) -> Point:
    """Return the west north west anchor of the text layout."""
    return self.bbox().west_north_west()

west_south_west

west_south_west() -> Point

Return the west south west anchor of the text layout.

Source code in src/momapy/core/layout.py
def west_south_west(self) -> Point:
    """Return the west south west anchor of the text layout."""
    return self.bbox().west_south_west()

x property

x: float

Return the x coordinate of the text layout.

y property

y: float

Return the y coordinate of the text layout.

VAlignment

Bases: Enum

Vertical alignment of text or content.

Selects how content is positioned along the vertical axis.