Core - momapy

Skip to content

# Core

## `` momapy.rendering.core

Bases classes and functions for rendering maps or layout elements

Classes:

Name | Description
--- | ---
`Renderer` | Base class for renderers
`StatefulRenderer` | Base class for stateful renderers

Functions:

Name | Description
--- | ---
`register_renderer` | Register a renderer class
`render_layout_element` | Render a layout element to a file in the given format with the given registered renderer
`render_layout_elements` | Render a collection of layout elements to a file in the given format with the given registered renderer
`render_map` | Render a map to a file in the given format with the given registered renderer
`render_maps` | Render a collection of maps to a file in the given format with the given registered renderer

### `` Renderer `dataclass`

    Renderer()

Bases: `ABC`

Base class for renderers

Methods:

Name | Description
--- | ---
`begin_session` | Begin a session
`end_session` | End a session
`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` | Make a new page
`render_drawing_element` | Render a drawing element
`render_layout_element` | Render a layout element
`render_map` | Render a map

#### `` begin_session `abstractmethod`

    begin_session()

Begin a session

Source code in `src/momapy/rendering/core.py`

    187
    188
    189
    190
    @abc.abstractmethod
    def begin_session(self):
        """Begin a session"""
        pass

#### `` end_session `abstractmethod`

    end_session()

End a session

Source code in `src/momapy/rendering/core.py`

    192
    193
    194
    195
    @abc.abstractmethod
    def end_session(self):
        """End a session"""
        pass

#### `` 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`

    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    @classmethod
    def get_bolder_font_weight(
        cls, font_weight: momapy.drawing.FontWeight | float
    ) -> float:
        """Return the lightest font weight bolder than the given font weight"""
        if isinstance(font_weight, momapy.drawing.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, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
                )
        if font_weight < 400:
            new_font_weight = 400
        elif font_weight < 600:
            new_font_weight = 700
        else:
            new_font_weight = 900
        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`

    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    @classmethod
    def get_lighter_font_weight(
        cls, font_weight: momapy.drawing.FontWeight | float
    ) -> float:
        """Return the boldest font weight lighter than the given font weight"""
        if isinstance(font_weight, momapy.drawing.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, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
                )
        if font_weight > 700:
            new_font_weight = 700
        elif font_weight > 500:
            new_font_weight = 400
        else:
            new_font_weight = 100
        return new_font_weight

#### `` new_page `abstractmethod`

    new_page(width, height)

Make a new page

Source code in `src/momapy/rendering/core.py`

    197
    198
    199
    200
    @abc.abstractmethod
    def new_page(self, width, height):
        """Make a new page"""
        pass

#### `` render_drawing_element `abstractmethod`

    render_drawing_element(drawing_element: DrawingElement)

Render a drawing element

Source code in `src/momapy/rendering/core.py`

    212
    213
    214
    215
    @abc.abstractmethod
    def render_drawing_element(self, drawing_element: momapy.drawing.DrawingElement):
        """Render a drawing element"""
        pass

#### `` render_layout_element `abstractmethod`

    render_layout_element(layout_element: LayoutElement)

Render a layout element

Source code in `src/momapy/rendering/core.py`

    207
    208
    209
    210
    @abc.abstractmethod
    def render_layout_element(self, layout_element: momapy.core.LayoutElement):
        """Render a layout element"""
        pass

#### `` render_map `abstractmethod`

    render_map(map_: Map)

Render a map

Source code in `src/momapy/rendering/core.py`

    202
    203
    204
    205
    @abc.abstractmethod
    def render_map(self, map_: momapy.core.Map):
        """Render a map"""
        pass

### `` StatefulRenderer `dataclass`

    StatefulRenderer(
        _current_state: dict = dict(),
        _states: list[dict] = list(),
    )

Bases: `Renderer`

Base class for stateful renderers

Methods:

Name | Description
--- | ---
`begin_session` | Begin a session
`end_session` | End a session
`get_bolder_font_weight` | Return the lightest font weight bolder than the given font weight
`get_current_state` | Return the current state
`get_current_value` | Return the current value for an attribute
`get_initial_value` | Return the initial value for an attribute
`get_lighter_font_weight` | Return the boldest font weight lighter than the given font weight
`new_page` | Make a new page
`render_drawing_element` | Render a drawing element
`render_layout_element` | Render a layout element
`render_map` | Render a map
`restore` | Set the current state to the last saved state
`save` | Save the current state
`set_current_state` | Set the current state to the given state
`set_current_state_from_drawing_element` | Set the current state to a state given by a drawing element
`set_current_value` | Set the current value for an attribute

#### `` begin_session `abstractmethod`

    begin_session()

Begin a session

Source code in `src/momapy/rendering/core.py`

    187
    188
    189
    190
    @abc.abstractmethod
    def begin_session(self):
        """Begin a session"""
        pass

#### `` end_session `abstractmethod`

    end_session()

End a session

Source code in `src/momapy/rendering/core.py`

    192
    193
    194
    195
    @abc.abstractmethod
    def end_session(self):
        """End a session"""
        pass

#### `` 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`

    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    @classmethod
    def get_bolder_font_weight(
        cls, font_weight: momapy.drawing.FontWeight | float
    ) -> float:
        """Return the lightest font weight bolder than the given font weight"""
        if isinstance(font_weight, momapy.drawing.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, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
                )
        if font_weight < 400:
            new_font_weight = 400
        elif font_weight < 600:
            new_font_weight = 700
        else:
            new_font_weight = 900
        return new_font_weight

#### `` get_current_state

    get_current_state() -> dict[str, Any]

Return the current state

Source code in `src/momapy/rendering/core.py`

    320
    321
    322
    def get_current_state(self) -> dict[str, typing.Any]:
        """Return the current state"""
        return self._current_state

#### `` get_current_value

    get_current_value(attr_name: str) -> Any

Return the current value for an attribute

Source code in `src/momapy/rendering/core.py`

    316
    317
    318
    def get_current_value(self, attr_name: str) -> typing.Any:
        """Return the current value for an attribute"""
        return self.get_current_state()[attr_name]

#### `` get_initial_value

    get_initial_value(attr_name: str) -> Any

Return the initial value for an attribute

Source code in `src/momapy/rendering/core.py`

    306
    307
    308
    309
    310
    311
    312
    313
    314
    def get_initial_value(self, attr_name: str) -> typing.Any:
        """Return the initial value for an attribute"""
        attr_value = self.initial_values.get(attr_name)
        if attr_value is None:
            attr_d = momapy.drawing.PRESENTATION_ATTRIBUTES[attr_name]
            attr_value = attr_d["initial"]
            if attr_value is None:
                attr_value = momapy.drawing.INITIAL_VALUES[attr_name]
        return attr_value

#### `` 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`

    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    @classmethod
    def get_lighter_font_weight(
        cls, font_weight: momapy.drawing.FontWeight | float
    ) -> float:
        """Return the boldest font weight lighter than the given font weight"""
        if isinstance(font_weight, momapy.drawing.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, {momapy.drawing.FontWeight.NORMAL}, or {momapy.drawing.FontWeight.BOLD}"
                )
        if font_weight > 700:
            new_font_weight = 700
        elif font_weight > 500:
            new_font_weight = 400
        else:
            new_font_weight = 100
        return new_font_weight

#### `` new_page `abstractmethod`

    new_page(width, height)

Make a new page

Source code in `src/momapy/rendering/core.py`

    197
    198
    199
    200
    @abc.abstractmethod
    def new_page(self, width, height):
        """Make a new page"""
        pass

#### `` render_drawing_element `abstractmethod`

    render_drawing_element(drawing_element: DrawingElement)

Render a drawing element

Source code in `src/momapy/rendering/core.py`

    212
    213
    214
    215
    @abc.abstractmethod
    def render_drawing_element(self, drawing_element: momapy.drawing.DrawingElement):
        """Render a drawing element"""
        pass

#### `` render_layout_element `abstractmethod`

    render_layout_element(layout_element: LayoutElement)

Render a layout element

Source code in `src/momapy/rendering/core.py`

    207
    208
    209
    210
    @abc.abstractmethod
    def render_layout_element(self, layout_element: momapy.core.LayoutElement):
        """Render a layout element"""
        pass

#### `` render_map `abstractmethod`

    render_map(map_: Map)

Render a map

Source code in `src/momapy/rendering/core.py`

    202
    203
    204
    205
    @abc.abstractmethod
    def render_map(self, map_: momapy.core.Map):
        """Render a map"""
        pass

#### `` restore

    restore()

Set the current state to the last saved state

Source code in `src/momapy/rendering/core.py`

    297
    298
    299
    300
    301
    302
    303
    304
    def restore(self):
        """Set the current state to the last saved state"""
        if len(self._states) > 0:
            state = self._states.pop()
            self.set_current_state(state)
            self.self_restore()
        else:
            raise Exception("no state to be restored")

#### `` save

    save()

Save the current state

Source code in `src/momapy/rendering/core.py`

    292
    293
    294
    295
    def save(self):
        """Save the current state"""
        self._states.append(copy.deepcopy(self.get_current_state()))
        self.self_save()

#### `` set_current_state

    set_current_state(state: dict)

Set the current state to the given state

Source code in `src/momapy/rendering/core.py`

    352
    353
    354
    355
    def set_current_state(self, state: dict):
        """Set the current state to the given state"""
        for attr_name, attr_value in state.items():
            self.set_current_value(attr_name, attr_value)

#### `` set_current_state_from_drawing_element

    set_current_state_from_drawing_element(
        drawing_element: DrawingElement,
    )

Set the current state to a state given by a drawing element

Source code in `src/momapy/rendering/core.py`

    363
    364
    365
    366
    367
    368
    def set_current_state_from_drawing_element(
        self, drawing_element: momapy.drawing.DrawingElement
    ):
        """Set the current state to a state given by a drawing element"""
        state = self._get_state_from_drawing_element(drawing_element)
        self.set_current_state(state)

#### `` set_current_value

    set_current_value(attr_name: str, attr_value: Any)

Set the current value for an attribute

Source code in `src/momapy/rendering/core.py`

    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    def set_current_value(self, attr_name: str, attr_value: typing.Any):
        """Set the current value for an attribute"""
        if attr_value is None:
            attr_d = momapy.drawing.PRESENTATION_ATTRIBUTES[attr_name]
            if not attr_d["inherited"]:
                attr_value = self.initial_values.get(attr_name)
                if attr_value is None:
                    attr_value = attr_d["initial"]
                if attr_value is None:
                    attr_value = momapy.drawing.INITIAL_VALUES[attr_name]
        if attr_name == "font_weight":
            if isinstance(attr_value, momapy.drawing.FontWeight):
                if (
                    attr_value == momapy.drawing.FontWeight.NORMAL
                    or attr_value == momapy.drawing.FontWeight.BOLD
                ):
                    attr_value = self.font_weight_value_mapping[attr_value]
                elif attr_value == momapy.drawing.FontWeight.BOLDER:
                    attr_value = self.get_bolder_font_weight(
                        self.get_current_value("font_weight")
                    )
                elif attr_value == momapy.drawing.FontWeight.LIGHTER:
                    attr_value = self.get_lighter_font_weight(
                        self.get_current_value("font_weight")
                    )
        if attr_value is not None:
            self._current_state[attr_name] = attr_value

### `` register_renderer

    register_renderer(name, renderer_cls)

Register a renderer class

Source code in `src/momapy/rendering/core.py`

    20
    21
    22
    def register_renderer(name, renderer_cls):
        """Register a renderer class"""
        renderers[name] = renderer_cls

### `` render_layout_element

    render_layout_element(
        layout_element: LayoutElement,
        file_path: str | PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: StyleSheet | None = None,
        to_top_left: bool = False,
    )

Render a layout element to a file in the given format with the given registered renderer

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`layout_element` | `LayoutElement` | The layout element to render | required
`file_path` | `str | PathLike` | The output file path | required
`format_` | `str` | The output format | `'pdf'`
`renderer` | `str` | The registered renderer to use. See register_renderer to register renderers | `'skia'`
`style_sheet` | `StyleSheet | None` | An optional style sheet to apply before rendering | `None`
`to_top_left` | `bool` | Whether to move the layout element to the top left or not before rendering | `False`

Source code in `src/momapy/rendering/core.py`

    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    def render_layout_element(
        layout_element: momapy.core.LayoutElement,
        file_path: str | os.PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: momapy.styling.StyleSheet | None = None,
        to_top_left: bool = False,
    ):
        """Render a layout element to a file in the given format with the given registered renderer

        Args:
            layout_element: The layout element to render
            file_path: The output file path
            format_: The output format
            renderer: The registered renderer to use. See [register_renderer][momapy.rendering.core.register_renderer] to register renderers
            style_sheet: An optional style sheet to apply before rendering
            to_top_left: Whether to move the layout element to the top left or not before rendering
        """
        render_layout_elements(
            layout_elements=[layout_element],
            file_path=file_path,
            format_=format_,
            renderer=renderer,
            style_sheet=style_sheet,
            to_top_left=to_top_left,
        )

### `` render_layout_elements

    render_layout_elements(
        layout_elements: Collection[LayoutElement],
        file_path: str | PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: StyleSheet | None = None,
        to_top_left: bool = False,
        multi_pages: bool = True,
    )

Render a collection of layout elements to a file in the given format with the given registered renderer

Source code in `src/momapy/rendering/core.py`

     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    def render_layout_elements(
        layout_elements: collections.abc.Collection[momapy.core.LayoutElement],
        file_path: str | os.PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: momapy.styling.StyleSheet | None = None,
        to_top_left: bool = False,
        multi_pages: bool = True,
    ):
        """Render a collection of layout elements to a file in the given format with the given registered renderer"""

        def _prepare_layout_elements(layout_elements, style_sheet=None, to_top_left=False):
            bboxes = [layout_element.bbox() for layout_element in layout_elements]
            bbox = momapy.positioning.fit(bboxes)
            max_x = bbox.x + bbox.width / 2
            max_y = bbox.y + bbox.height / 2
            if style_sheet is not None or to_top_left:
                new_layout_elements = []
                for layout_element in layout_elements:
                    if isinstance(layout_element, momapy.core.LayoutElement):
                        new_layout_elements.append(
                            momapy.builder.builder_from_object(layout_element)
                        )
                    elif isinstance(layout_element, momapy.core.LayoutElementBuilder):
                        new_layout_elements.append(copy.deepcopy(layout_element))
                layout_elements = new_layout_elements
            if style_sheet is not None:
                if (
                    not isinstance(style_sheet, collections.abc.Collection)
                    or isinstance(style_sheet, str)
                    or isinstance(style_sheet, momapy.styling.StyleSheet)
                ):
                    style_sheets = [style_sheet]
                else:
                    style_sheets = style_sheet
                style_sheets = [
                    (
                        momapy.styling.StyleSheet.from_file(style_sheet)
                        if not isinstance(style_sheet, momapy.styling.StyleSheet)
                        else style_sheet
                    )
                    for style_sheet in style_sheets
                ]
                style_sheet = momapy.styling.combine_style_sheets(style_sheets)
                for layout_element in layout_elements:
                    momapy.styling.apply_style_sheet(layout_element, style_sheet)
            if to_top_left:
                min_x = bbox.x - bbox.width / 2
                min_y = bbox.y - bbox.height / 2
                max_x -= min_x
                max_y -= min_y
                translation = momapy.geometry.Translation(-min_x, -min_y)
                for layout_element in layout_elements:
                    if layout_element.group_transform is None:
                        layout_element.group_transform = momapy.core.TupleBuilder()
                    layout_element.group_transform.append(translation)
            return layout_elements, max_x, max_y

        if not multi_pages:
            prepared_layout_elements, max_x, max_y = _prepare_layout_elements(
                layout_elements, style_sheet, to_top_left
            )
            renderer = renderers[renderer].from_file(file_path, max_x, max_y, format_)
            renderer.begin_session()
            for prepared_layout_element in prepared_layout_elements:
                renderer.render_layout_element(prepared_layout_element)
            renderer.end_session()
        else:
            if layout_elements:
                layout_element = layout_elements[0]
                prepared_layout_elements, max_x, max_y = _prepare_layout_elements(
                    [layout_element], style_sheet, to_top_left
                )
                renderer = renderers[renderer].from_file(file_path, max_x, max_y, format_)
                renderer.begin_session()
                renderer.render_layout_element(prepared_layout_elements[0])
                for layout_element in layout_elements[1:]:
                    prepared_layout_elements, max_x, max_y = _prepare_layout_elements(
                        [layout_element], style_sheet, to_top_left
                    )
                    renderer.new_page(max_x, max_y)
                    renderer.render_layout_element(prepared_layout_elements[0])
            else:
                renderer = renderers[renderer].from_file(file_path, 0, 0, format_)
            renderer.end_session()

### `` render_map

    render_map(
        map_: Map,
        file_path: str | PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: StyleSheet | None = None,
        to_top_left: bool = False,
    )

Render a map to a file in the given format with the given registered renderer

Source code in `src/momapy/rendering/core.py`

    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    def render_map(
        map_: momapy.core.Map,
        file_path: str | os.PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: momapy.styling.StyleSheet | None = None,
        to_top_left: bool = False,
    ):
        """Render a map to a file in the given format with the given registered renderer"""
        render_maps([map_], file_path, format_, renderer, style_sheet, to_top_left)

### `` render_maps

    render_maps(
        maps: Collection[Map],
        file_path: str | PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: StyleSheet | None = None,
        to_top_left: bool = False,
        multi_pages: bool = True,
    )

Render a collection of maps to a file in the given format with the given registered renderer

Source code in `src/momapy/rendering/core.py`

    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    def render_maps(
        maps: collections.abc.Collection[momapy.core.Map],
        file_path: str | os.PathLike,
        format_: str = "pdf",
        renderer: str = "skia",
        style_sheet: momapy.styling.StyleSheet | None = None,
        to_top_left: bool = False,
        multi_pages: bool = True,
    ):
        """Render a collection of maps to a file in the given format with the given registered renderer"""
        layout_elements = [map_.layout for map_ in maps]
        render_layout_elements(
            layout_elements=layout_elements,
            file_path=file_path,
            format_=format_,
            renderer=renderer,
            style_sheet=style_sheet,
            to_top_left=to_top_left,
            multi_pages=multi_pages,
        )