Skip to content

SBGN-AF labels

pd2af.building.sbgn.labels

Make the label of an SBGN-AF activity from an SBGN-PD entity pool.

SBGN-AF activities are opaque, so two distinct PD proteoforms (same type and name, different state) would collapse under content-based model equality unless their distinguishing fields are folded into the activity's content. We do that through the activity label, built from the entity's units of information, state variables and name:

[unit|of|information][state@variables]name

Rules:

  • The entity type and its compartment are not part of the label (the type is carried by the activity's unit-of-information glyph).
  • Units of information are rendered prefix:value (or value with no prefix) and sorted (they carry no order). When inlined in the activity label they sit in a [...] bracket; on the unit-of-information glyph they carry no brackets (the brackets are the label serialization device only). In the merged reading (keep_species off) (include_units_of_information=False) this block is not inlined into the label: a curator building an AF map from scratch writes ct:mRNA on the nucleic-acid-feature glyph, never [ct:mRNA] in the label. The block (see :func:make_units_of_information_label) is instead placed on the activity's typed unit-of-information glyph by the model builder. The block is still kept inline for a complex's recursively built subunit name (below), which is a synthetic identity key, not a curator-facing label, so it stays maximally distinguishing.
  • State variables are rendered value@variable (@variable with no value, value with no variable, empty when neither) and listed in their order so multi-site proteoforms stay positionally distinct without showing the order number. An all-blank state-variable set renders no bracket.
  • A complex's subunits are not part of its name when the complex has its own label; for an unlabelled complex the name is its subunits, built recursively and joined by :.

There are no spaces between elements.

Functions:

Name Description
make_label

Return the SBGN-AF activity label for an SBGN-PD entity pool or subunit.

make_units_of_information_label

Return the unit-of-information glyph label for an SBGN-PD element.

make_label

make_label(entity_pool_or_subunit: Any, include_state_variables: bool = True, include_units_of_information: bool = True) -> str

Return the SBGN-AF activity label for an SBGN-PD entity pool or subunit.

The rules are those given in the module docstring.

When include_state_variables is False the state-variable block is omitted so that distinct proteoforms (same type/name/units, different state) collapse into a single merged activity.

When include_units_of_information is False the unit-of-information block is omitted too -- the merged reading (keep_species off) relocates it to the activity's unit-of-information glyph instead of inlining it. The keep_species option keeps both blocks (the defaults).

Source code in src/pd2af/building/sbgn/labels.py
def make_label(
    entity_pool_or_subunit: typing.Any,
    include_state_variables: bool = True,
    include_units_of_information: bool = True,
) -> str:
    """Return the SBGN-AF activity label for an SBGN-PD entity pool or subunit.

    The rules are those given in the module docstring.

    When ``include_state_variables`` is ``False`` the state-variable block is
    omitted so that distinct proteoforms (same type/name/units, different state)
    collapse into a single merged activity.

    When ``include_units_of_information`` is ``False`` the unit-of-information
    block is omitted too -- the merged reading (``keep_species`` off) relocates
    it to the activity's unit-of-information glyph instead of inlining it. The
    ``keep_species`` option keeps both blocks (the defaults).
    """
    decorations = ""
    if include_units_of_information:
        units_label = make_units_of_information_label(entity_pool_or_subunit)
        if units_label:
            # Brackets are the activity-label serialization device only; the
            # glyph label (the helper's return value) carries none.
            decorations += f"[{units_label}]"
    state_variables = getattr(entity_pool_or_subunit, "state_variables", None)
    if include_state_variables and state_variables:
        tokens = [
            _make_state_variable_token(state_variable)
            for state_variable in sorted(
                state_variables, key=_make_state_variable_sort_key
            )
        ]
        if any(tokens):  # omit an all-blank state-variable bracket
            decorations += "[" + "|".join(tokens) + "]"
    name = getattr(entity_pool_or_subunit, "label", None) or ""
    if not name:
        subunits = getattr(entity_pool_or_subunit, "subunits", None)
        if subunits:
            # An unlabelled complex's name is its subunits' labels. This name is
            # a synthetic identity key (a curator would name the complex or leave
            # it blank, never write ``A:B``), so subunit units of information stay
            # inline -- only the top-level entity's own units relocate to the
            # glyph -- keeping distinct complexes distinct. State variables still
            # follow ``include_state_variables`` (they are decoration, merged away
            # recursively in the merged modes).
            name = ":".join(
                sorted(
                    make_label(
                        subunit,
                        include_state_variables=include_state_variables,
                        include_units_of_information=True,
                    )
                    for subunit in subunits
                )
            )
    if decorations and name:
        return f"{decorations}{name}"
    return decorations or name

make_units_of_information_label

make_units_of_information_label(entity_pool_or_subunit: Any) -> str | None

Return the unit-of-information glyph label for an SBGN-PD element.

The label is uoi1|uoi2|... -- tokens prefix:value (or value with no prefix), sorted, joined by | -- or None when entity_pool_or_subunit carries no units of information.

The merged reading (keep_species off) moves this off the activity label and onto the AF activity's typed unit-of-information glyph (see :func:pd2af.building.sbgn.model._make_activity), where a curator would put it -- e.g. ct:mRNA on a nucleic-acid-feature glyph. It carries no surrounding brackets: those are only the activity-label serialization device (added by :func:make_label), not part of the glyph text.

Source code in src/pd2af/building/sbgn/labels.py
def make_units_of_information_label(entity_pool_or_subunit: typing.Any) -> str | None:
    """Return the unit-of-information glyph label for an SBGN-PD element.

    The label is ``uoi1|uoi2|...`` -- tokens ``prefix:value`` (or ``value`` with
    no prefix), sorted, joined by ``|`` -- or ``None`` when
    ``entity_pool_or_subunit`` carries no units of information.

    The merged reading (``keep_species`` off) moves this off the activity
    *label* and onto the AF activity's typed unit-of-information glyph (see
    :func:`pd2af.building.sbgn.model._make_activity`), where a curator would put
    it -- e.g. ``ct:mRNA`` on a nucleic-acid-feature glyph. It carries **no**
    surrounding brackets: those are only the activity-label serialization device
    (added by :func:`make_label`), not part of the glyph text.
    """
    units_of_information = getattr(entity_pool_or_subunit, "units_of_information", None)
    if not units_of_information:
        return None
    return "|".join(
        sorted(_make_unit_of_information_token(unit) for unit in units_of_information)
    )