Skip to content

SVG-native

momapy.rendering.svg_native

Classes for rendering in the SVG format.

Classes:

Name Description
SVGElement

Class for SVG elements.

SVGNativeCompatRenderer

Renderer for SVG with compatibility mode filters.

SVGNativeRenderer

Renderer implementation for generating native SVG output.

SVGElement dataclass

SVGElement(name: str, value: str | None = None, attributes: dict[str, Any] = dict(), elements: list[SVGElement] = list())

Bases: object

Class for SVG elements.

This class represents an SVG element with a name, optional text value, attributes, and child elements.

Examples:

element = SVGElement(
    name="rect",
    attributes={"x": "0", "y": "0", "width": "100", "height": "100"}
)
print(element)

Parameters:

Name Type Description Default
name str

The tag name of the SVG element (e.g. 'svg', 'rect', 'path')

required
value str | None

The optional text content of the element

None
attributes dict[str, Any]

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

<class 'dict'>
elements list[str]

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

<dynamic>

Methods:

Name Description
__str__

Return the SVG string representation of the element.

add_element

Add a sub-element to the SVG element.

to_string

Return the SVG string representing the element.

__str__

__str__() -> str

Return the SVG string representation of the element.

Source code in src/momapy/rendering/svg_native.py
def __str__(self) -> str:
    """Return the SVG string representation of the element."""
    return self.to_string()

add_element

add_element(element: SVGElement) -> None

Add a sub-element to the SVG element.

Parameters:

Name Type Description Default
element SVGElement

The child SVGElement to add

required
Source code in src/momapy/rendering/svg_native.py
def add_element(self, element: "SVGElement") -> None:
    """Add a sub-element to the SVG element.

    Args:
        element: The child SVGElement to add
    """
    self.elements.append(element)

to_string

to_string(indent: int = 0) -> str

Return the SVG string representing the element.

Parameters:

Name Type Description Default
indent int

The indentation level (number of tabs)

0

Returns:

Type Description
str

The SVG markup as a string

Source code in src/momapy/rendering/svg_native.py
def to_string(self, indent: int = 0) -> str:
    """Return the SVG string representing the element.

    Args:
        indent: The indentation level (number of tabs)

    Returns:
        The SVG markup as a string
    """
    s_indent = "\t" * indent
    s_value = f"{s_indent}{self.value}\n" if self.value is not None else ""
    if self.attributes:
        l_s_attributes = []
        for attr_name, attr_value in self.attributes.items():
            s_attr_name = attr_name
            s_attr_value = f'"{attr_value}"'
            s_attribute = f"{s_attr_name}={s_attr_value}"
            l_s_attributes.append(s_attribute)
        s_attributes = f" {' '.join(l_s_attributes)}"
    else:
        s_attributes = ""
    if self.elements:
        s_elements = "\n".join(
            [child.to_string(indent + 1) for child in self.elements]
        )
        s_elements += "\n"
    else:
        s_elements = ""
    return f"{s_indent}<{self.name}{s_attributes}>\n{s_value}{s_elements}{s_indent}</{self.name}>"

SVGNativeCompatRenderer dataclass

SVGNativeCompatRenderer(svg: SVGElement, _config: dict[str, Any] = dict(), _filter_elements: list[SVGElement] = list())

Bases: SVGNativeRenderer

Renderer for SVG with compatibility mode filters.

This renderer extends SVGNativeRenderer to provide compatibility with older SVG viewers by converting filters to a compatible format.

Examples:

renderer = SVGNativeCompatRenderer.from_file("output.svg", 800, 600, "svg")
renderer.begin_session()
renderer.render_layout_element(layout_element)
renderer.end_session()

Parameters:

Name Type Description Default
svg SVGElement

The root SVG element that will contain all rendered content

required

Methods:

Name Description
begin_session

Begin a rendering session.

end_session

End the rendering session and save the output.

from_file

Create an SVGNativeRenderer instance from a file path.

get_bolder_font_weight

Return the lightest font weight bolder than the given font weight.

get_lighter_font_weight

Return the boldest font weight lighter than the given font weight.

new_page

Create a new page in the output document.

render_drawing_element

Render a drawing element to the output.

render_layout_element

Render a layout element to the output.

render_map

Render a map.

Attributes:

Name Type Description
default_format str | None

The format used when from_file is called with format_=None.

begin_session

begin_session() -> None

Begin a rendering session.

This method initializes the rendering context. For SVGNativeRenderer, no explicit initialization is needed as the SVG element is created during instantiation.

Source code in src/momapy/rendering/svg_native.py
def begin_session(self) -> None:
    """Begin a rendering session.

    This method initializes the rendering context. For SVGNativeRenderer,
    no explicit initialization is needed as the SVG element is created
    during instantiation.
    """
    pass

default_format class-attribute

default_format: str | None = 'svg'

The format used when from_file is called with format_=None.

Subclasses set this to one of their :attr:supported_formats.

end_session

end_session() -> None

End the rendering session and save the output.

This method finalizes the SVG document, adds any filter definitions to the defs section, and writes the output to the file.

Source code in src/momapy/rendering/svg_native.py
def end_session(self) -> None:
    """End the rendering session and save the output.

    This method finalizes the SVG document, adds any filter definitions
    to the defs section, and writes the output to the file.
    """
    if self._filter_elements:
        defs = SVGElement(name="defs", elements=self._filter_elements)
        self.svg.add_element(defs)
    if self._config.get("output_file") is not None:
        with open(self._config["output_file"], "w", encoding="utf-8") as f:
            f.write(str(self.svg))

from_file classmethod

from_file(file_path: str | PathLike, width: float, height: float, format_: str | None = None) -> Self

Create an SVGNativeRenderer instance from a file path.

Parameters:

Name Type Description Default
file_path str | PathLike

The output file path

required
width float

The width of the SVG canvas

required
height float

The height of the SVG canvas

required
format_ str | None

The output format. None selects the backend's :attr:default_format ("svg").

None

Returns:

Type Description
Self

A new SVGNativeRenderer instance

Raises:

Type Description
ValueError

If the format is not supported

Examples:

renderer = SVGNativeRenderer.from_file("output.svg", 800, 600, "svg")
Source code in src/momapy/rendering/svg_native.py
@classmethod
def from_file(
    cls,
    file_path: str | os.PathLike,
    width: float,
    height: float,
    format_: str | None = None,
) -> typing_extensions.Self:
    """Create an SVGNativeRenderer instance from a file path.

    Args:
        file_path: The output file path
        width: The width of the SVG canvas
        height: The height of the SVG canvas
        format_: The output format. ``None`` selects the backend's
            :attr:`default_format` ("svg").

    Returns:
        A new SVGNativeRenderer instance

    Raises:
        ValueError: If the format is not supported

    Examples:
        ```python
        renderer = SVGNativeRenderer.from_file("output.svg", 800, 600, "svg")
        ```
    """
    if format_ is None:
        format_ = cls.default_format
    if format_ not in cls.supported_formats:
        raise ValueError(
            f"unsupported format {format_!r}: expected one of "
            f"{', '.join(cls.supported_formats)}"
        )
    check_parent_dir_exists(file_path)
    config = {}
    config["output_file"] = file_path
    config["width"] = width
    config["height"] = height
    config["format"] = format_
    svg = SVGElement(
        name="svg",
        attributes={
            "xmlns": "http://www.w3.org/2000/svg",
            "viewBox": f"0 0 {width} {height}",
        },
    )
    return cls(svg=svg, _config=config)

get_bolder_font_weight classmethod

get_bolder_font_weight(font_weight: FontWeight | float) -> float

Return the lightest font weight bolder than the given font weight.

Source code in src/momapy/rendering/core.py
@classmethod
def get_bolder_font_weight(cls, font_weight: FontWeight | float) -> float:
    """Return the lightest font weight bolder than the given font weight."""
    if isinstance(font_weight, FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {FontWeight.NORMAL}, or {FontWeight.BOLD}"
            )
    if font_weight < 400:
        new_font_weight = 400.0
    elif font_weight < 600:
        new_font_weight = 700.0
    else:
        new_font_weight = 900.0
    return new_font_weight

get_lighter_font_weight classmethod

get_lighter_font_weight(font_weight: FontWeight | float) -> float

Return the boldest font weight lighter than the given font weight.

Source code in src/momapy/rendering/core.py
@classmethod
def get_lighter_font_weight(cls, font_weight: FontWeight | float) -> float:
    """Return the boldest font weight lighter than the given font weight."""
    if isinstance(font_weight, FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {FontWeight.NORMAL}, or {FontWeight.BOLD}"
            )
    if font_weight > 700:
        new_font_weight = 700.0
    elif font_weight > 500:
        new_font_weight = 400.0
    else:
        new_font_weight = 100.0
    return new_font_weight

new_page

new_page(width: float, height: float) -> None

Create a new page in the output document.

Parameters:

Name Type Description Default
width float

The width of the new page

required
height float

The height of the new page

required
Note

SVG format does not support multiple pages. This method is a no-op.

Source code in src/momapy/rendering/svg_native.py
def new_page(self, width: float, height: float) -> None:
    """Create a new page in the output document.

    Args:
        width: The width of the new page
        height: The height of the new page

    Note:
        SVG format does not support multiple pages. This method is a no-op.
    """
    pass

render_drawing_element

render_drawing_element(drawing_element: DrawingElement) -> None

Render a drawing element to the output.

Parameters:

Name Type Description Default
drawing_element DrawingElement

The drawing element to render

required

This method converts the drawing element to an SVG element and adds it to the SVG document.

Source code in src/momapy/rendering/svg_native.py
def render_drawing_element(self, drawing_element: DrawingElement) -> None:
    """Render a drawing element to the output.

    Args:
        drawing_element: The drawing element to render

    This method converts the drawing element to an SVG element
    and adds it to the SVG document.
    """
    element = self._make_drawing_element_element(drawing_element)
    self.svg.add_element(element)

render_layout_element

render_layout_element(layout_element: LayoutElement) -> None

Render a layout element to the output.

Parameters:

Name Type Description Default
layout_element LayoutElement

The layout element to render

required
Source code in src/momapy/rendering/svg_native.py
def render_layout_element(self, layout_element: LayoutElement) -> None:
    """Render a layout element to the output.

    Args:
        layout_element: The layout element to render
    """
    drawing_elements = layout_element.drawing_elements()
    for drawing_element in drawing_elements:
        self.render_drawing_element(drawing_element)

render_map

render_map(map_: Map) -> None

Render a map.

This is a convenience method, not part of the abstract contract: the default implementation renders the map's layout via :meth:render_layout_element, which is what every built-in backend needs. Subclasses may override it if a backend requires map-specific handling, but they are not obliged to. The file pipeline (:func:render_map/:func:render_maps) does not call this method; it renders each page through :meth:render_layout_element.

Parameters:

Name Type Description Default
map_ Map

The map to render.

required

Raises:

Type Description
ValueError

If the map has no layout to render.

Source code in src/momapy/rendering/core.py
def render_map(self, map_: Map) -> None:
    """Render a map.

    This is a convenience method, **not** part of the abstract
    contract: the default implementation renders the map's layout via
    :meth:`render_layout_element`, which is what every built-in backend
    needs. Subclasses may override it if a backend requires
    map-specific handling, but they are not obliged to. The file
    pipeline (:func:`render_map`/:func:`render_maps`) does not call this
    method; it renders each page through :meth:`render_layout_element`.

    Args:
        map_: The map to render.

    Raises:
        ValueError: If the map has no layout to render.
    """
    if map_.layout is None:
        raise ValueError(
            "map has no layout to render (its layout is None); "
            "a layout-less map (e.g. an SBML map) cannot be rendered"
        )
    self.render_layout_element(map_.layout)

SVGNativeRenderer dataclass

SVGNativeRenderer(svg: SVGElement, _config: dict[str, Any] = dict(), _filter_elements: list[SVGElement] = list())

Bases: Renderer, SupportsFileOutput

Renderer implementation for generating native SVG output.

This renderer creates SVG markup directly without external dependencies. It supports all standard SVG features including filters, transformations, and presentation attributes.

Examples:

from momapy.meta.nodes import Rectangle
import momapy.geometry

# Create a layout element to render
node = Rectangle(
    position=momapy.geometry.Point(100.0, 100.0),
    width=200.0,
    height=100.0
)

# Create renderer and render the element
renderer = SVGNativeRenderer.from_file("output.svg", 800, 600, "svg")
renderer.begin_session()
renderer.render_layout_element(node)
renderer.end_session()

Parameters:

Name Type Description Default
svg SVGElement

The root SVG element that will contain all rendered content

required

Methods:

Name Description
begin_session

Begin a rendering session.

end_session

End the rendering session and save the output.

from_file

Create an SVGNativeRenderer instance from a file path.

get_bolder_font_weight

Return the lightest font weight bolder than the given font weight.

get_lighter_font_weight

Return the boldest font weight lighter than the given font weight.

new_page

Create a new page in the output document.

render_drawing_element

Render a drawing element to the output.

render_layout_element

Render a layout element to the output.

render_map

Render a map.

Attributes:

Name Type Description
default_format str | None

The format used when from_file is called with format_=None.

begin_session

begin_session() -> None

Begin a rendering session.

This method initializes the rendering context. For SVGNativeRenderer, no explicit initialization is needed as the SVG element is created during instantiation.

Source code in src/momapy/rendering/svg_native.py
def begin_session(self) -> None:
    """Begin a rendering session.

    This method initializes the rendering context. For SVGNativeRenderer,
    no explicit initialization is needed as the SVG element is created
    during instantiation.
    """
    pass

default_format class-attribute

default_format: str | None = 'svg'

The format used when from_file is called with format_=None.

Subclasses set this to one of their :attr:supported_formats.

end_session

end_session() -> None

End the rendering session and save the output.

This method finalizes the SVG document, adds any filter definitions to the defs section, and writes the output to the file.

Source code in src/momapy/rendering/svg_native.py
def end_session(self) -> None:
    """End the rendering session and save the output.

    This method finalizes the SVG document, adds any filter definitions
    to the defs section, and writes the output to the file.
    """
    if self._filter_elements:
        defs = SVGElement(name="defs", elements=self._filter_elements)
        self.svg.add_element(defs)
    if self._config.get("output_file") is not None:
        with open(self._config["output_file"], "w", encoding="utf-8") as f:
            f.write(str(self.svg))

from_file classmethod

from_file(file_path: str | PathLike, width: float, height: float, format_: str | None = None) -> Self

Create an SVGNativeRenderer instance from a file path.

Parameters:

Name Type Description Default
file_path str | PathLike

The output file path

required
width float

The width of the SVG canvas

required
height float

The height of the SVG canvas

required
format_ str | None

The output format. None selects the backend's :attr:default_format ("svg").

None

Returns:

Type Description
Self

A new SVGNativeRenderer instance

Raises:

Type Description
ValueError

If the format is not supported

Examples:

renderer = SVGNativeRenderer.from_file("output.svg", 800, 600, "svg")
Source code in src/momapy/rendering/svg_native.py
@classmethod
def from_file(
    cls,
    file_path: str | os.PathLike,
    width: float,
    height: float,
    format_: str | None = None,
) -> typing_extensions.Self:
    """Create an SVGNativeRenderer instance from a file path.

    Args:
        file_path: The output file path
        width: The width of the SVG canvas
        height: The height of the SVG canvas
        format_: The output format. ``None`` selects the backend's
            :attr:`default_format` ("svg").

    Returns:
        A new SVGNativeRenderer instance

    Raises:
        ValueError: If the format is not supported

    Examples:
        ```python
        renderer = SVGNativeRenderer.from_file("output.svg", 800, 600, "svg")
        ```
    """
    if format_ is None:
        format_ = cls.default_format
    if format_ not in cls.supported_formats:
        raise ValueError(
            f"unsupported format {format_!r}: expected one of "
            f"{', '.join(cls.supported_formats)}"
        )
    check_parent_dir_exists(file_path)
    config = {}
    config["output_file"] = file_path
    config["width"] = width
    config["height"] = height
    config["format"] = format_
    svg = SVGElement(
        name="svg",
        attributes={
            "xmlns": "http://www.w3.org/2000/svg",
            "viewBox": f"0 0 {width} {height}",
        },
    )
    return cls(svg=svg, _config=config)

get_bolder_font_weight classmethod

get_bolder_font_weight(font_weight: FontWeight | float) -> float

Return the lightest font weight bolder than the given font weight.

Source code in src/momapy/rendering/core.py
@classmethod
def get_bolder_font_weight(cls, font_weight: FontWeight | float) -> float:
    """Return the lightest font weight bolder than the given font weight."""
    if isinstance(font_weight, FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {FontWeight.NORMAL}, or {FontWeight.BOLD}"
            )
    if font_weight < 400:
        new_font_weight = 400.0
    elif font_weight < 600:
        new_font_weight = 700.0
    else:
        new_font_weight = 900.0
    return new_font_weight

get_lighter_font_weight classmethod

get_lighter_font_weight(font_weight: FontWeight | float) -> float

Return the boldest font weight lighter than the given font weight.

Source code in src/momapy/rendering/core.py
@classmethod
def get_lighter_font_weight(cls, font_weight: FontWeight | float) -> float:
    """Return the boldest font weight lighter than the given font weight."""
    if isinstance(font_weight, FontWeight):
        font_weight = cls.font_weight_value_mapping.get(font_weight)
        if font_weight is None:
            raise ValueError(
                f"font weight must be a float, {FontWeight.NORMAL}, or {FontWeight.BOLD}"
            )
    if font_weight > 700:
        new_font_weight = 700.0
    elif font_weight > 500:
        new_font_weight = 400.0
    else:
        new_font_weight = 100.0
    return new_font_weight

new_page

new_page(width: float, height: float) -> None

Create a new page in the output document.

Parameters:

Name Type Description Default
width float

The width of the new page

required
height float

The height of the new page

required
Note

SVG format does not support multiple pages. This method is a no-op.

Source code in src/momapy/rendering/svg_native.py
def new_page(self, width: float, height: float) -> None:
    """Create a new page in the output document.

    Args:
        width: The width of the new page
        height: The height of the new page

    Note:
        SVG format does not support multiple pages. This method is a no-op.
    """
    pass

render_drawing_element

render_drawing_element(drawing_element: DrawingElement) -> None

Render a drawing element to the output.

Parameters:

Name Type Description Default
drawing_element DrawingElement

The drawing element to render

required

This method converts the drawing element to an SVG element and adds it to the SVG document.

Source code in src/momapy/rendering/svg_native.py
def render_drawing_element(self, drawing_element: DrawingElement) -> None:
    """Render a drawing element to the output.

    Args:
        drawing_element: The drawing element to render

    This method converts the drawing element to an SVG element
    and adds it to the SVG document.
    """
    element = self._make_drawing_element_element(drawing_element)
    self.svg.add_element(element)

render_layout_element

render_layout_element(layout_element: LayoutElement) -> None

Render a layout element to the output.

Parameters:

Name Type Description Default
layout_element LayoutElement

The layout element to render

required
Source code in src/momapy/rendering/svg_native.py
def render_layout_element(self, layout_element: LayoutElement) -> None:
    """Render a layout element to the output.

    Args:
        layout_element: The layout element to render
    """
    drawing_elements = layout_element.drawing_elements()
    for drawing_element in drawing_elements:
        self.render_drawing_element(drawing_element)

render_map

render_map(map_: Map) -> None

Render a map.

This is a convenience method, not part of the abstract contract: the default implementation renders the map's layout via :meth:render_layout_element, which is what every built-in backend needs. Subclasses may override it if a backend requires map-specific handling, but they are not obliged to. The file pipeline (:func:render_map/:func:render_maps) does not call this method; it renders each page through :meth:render_layout_element.

Parameters:

Name Type Description Default
map_ Map

The map to render.

required

Raises:

Type Description
ValueError

If the map has no layout to render.

Source code in src/momapy/rendering/core.py
def render_map(self, map_: Map) -> None:
    """Render a map.

    This is a convenience method, **not** part of the abstract
    contract: the default implementation renders the map's layout via
    :meth:`render_layout_element`, which is what every built-in backend
    needs. Subclasses may override it if a backend requires
    map-specific handling, but they are not obliged to. The file
    pipeline (:func:`render_map`/:func:`render_maps`) does not call this
    method; it renders each page through :meth:`render_layout_element`.

    Args:
        map_: The map to render.

    Raises:
        ValueError: If the map has no layout to render.
    """
    if map_.layout is None:
        raise ValueError(
            "map has no layout to render (its layout is None); "
            "a layout-less map (e.g. an SBML map) cannot be rendered"
        )
    self.render_layout_element(map_.layout)