Skip to content

SBGN-AF layout

pd2af.building.sbgn.layout

Build the SBGN-AF layout, in either plain or dot mode.

For each AF activity we build a fresh BiologicalActivityLayout / PhenotypeLayout with a typed unit-of-information sublayout and a label. Influence arcs are drawn afresh between the activity positions (PD arcs ran entity->process, so they cannot be copied). The layout_model_mapping is built per the catalogue in momapy/sbgn/af/__init__.py (singleton keys for activities and units of information; a frozenset key {arc, source, target} anchored on the arc for each influence).

Two layout modes:

  • plain -- reuse the curated SBGN-PD geometry: each activity is placed at its input element's layout position. An input element drawn with several layouts (a cloned entity pool) yields one activity layout per input layout, and influence arcs fan out across the source/target layouts per --influence-pairing (cross -- one arc per pair -- or nearest -- a single arc between the closest pair). Activities/compartments whose input has no layout are skipped.
  • dot -- build every element at a placeholder position with the default size, then hand the whole layout to pd2af.building.layout.make_auto_layout (graphviz) in build.py for repositioning. Required by the merged reading (keep_species off), where a merged activity has no single input layout.

overlay for SBGN-AF is unsupported (see pd2af.core).

Functions:

Name Description
make_and_add_layout

Build context.layout and context.layout_model_mapping (pass 2).

resolve_operator_arc_segments

Per-arc hook for :func:pd2af.building.layout.make_auto_layout's arc-geometry step.

make_and_add_layout

make_and_add_layout(context: BuilderContext)

Build context.layout and context.layout_model_mapping (pass 2).

Source code in src/pd2af/building/sbgn/layout.py
def make_and_add_layout(context: pd2af.building.context.BuilderContext):
    """Build ``context.layout`` and ``context.layout_model_mapping`` (pass 2)."""
    if context.layout_mode not in ("plain", "dot"):
        raise NotImplementedError(
            "SBGN-AF output supports the 'plain' and 'dot' layout modes "
            f"(got {context.layout_mode!r}); 'overlay' is unsupported."
        )
    context.layout = _builder(momapy.sbgn.af.SBGNAFLayout)
    context.layout_model_mapping = momapy.core.mapping.LayoutModelMappingBuilder()

    for compartment in context.model.compartments:
        _make_and_add_compartment_layout(context, compartment)
    for activity, input_element in context.activity_emissions:
        _make_and_add_activity_layout(context, activity, input_element)
    # Operators after activities (their logic arcs target activity layouts) and
    # before influences (an operator-sourced influence resolves its source
    # through the operator layout registered here).
    for operator, input_operator in context.operator_emissions:
        _make_and_add_operator_layout(context, operator, input_operator)
    for influence in context.model.influences:
        _make_and_add_influence_layout(context, influence)

    pd2af.building.layout.harmonize_root_layout(context.layout)

resolve_operator_arc_segments

resolve_operator_arc_segments(arc: Any, source_builder: Any, target_builder: Any) -> Any

Per-arc hook for :func:pd2af.building.layout.make_auto_layout's arc-geometry step.

When arc is sourced by an operator glyph, return its connector-attached segments recomputed from the graphviz-repositioned geometry; otherwise return None so the caller keeps its normal border geometry. This reuses the same connector helper as plain-mode arc creation, so the auto snap is folded into the recompute that already iterates every arc.

Source code in src/pd2af/building/sbgn/layout.py
def resolve_operator_arc_segments(
    arc: typing.Any, source_builder: typing.Any, target_builder: typing.Any
) -> typing.Any:
    """Per-arc hook for :func:`pd2af.building.layout.make_auto_layout`'s arc-geometry step.

    When ``arc`` is sourced by an operator glyph, return its connector-attached
    segments recomputed from the graphviz-repositioned geometry; otherwise
    return ``None`` so the caller keeps its normal border geometry. This reuses
    the same connector helper as plain-mode arc creation, so the auto snap is
    folded into the recompute that already iterates every arc.
    """
    if not momapy.builder.isinstance_or_builder(
        source_builder, _OPERATOR_LAYOUT_CLASSES
    ):
        return None
    is_logic_arc = momapy.builder.isinstance_or_builder(
        arc, momapy.sbgn.af.LogicArcLayout
    )
    return [_operator_connector_segment(source_builder, target_builder, is_logic_arc)]