Data Model

Molecular biology is a directed graph; not a table. BEL expresses how biological entities interact within many different contexts, with descriptive annotations. PyBEL represents data as a directional multigraph using an extension of networkx.MultiDiGraph. Each node and edge has an associated data dictionary for storing relevant/contextual information.

This allows for much easier programmatic access to answer more complicated questions, which can be written with python code. Because the data structure is the same in Neo4J, the data can be directly exported with pybel.to_neo4j(). Neo4J supports the Cypher querying language so that the same queries can be written in an elegant and simple way.

Constants

These documents refer to many aspects of the data model using constants, which can be found in the top-level module pybel.constants. In these examples, all constants are imported with the following code:

>>> from pybel.constants import *

Terms describing abundances, annotations, and other internal data are designated in pybel.constants with full-caps, such as pybel.constants.FUNCTION and pybel.constants.PROTEIN.

For normal usage, we suggest referring to values in dictionaries by these constants, in case the hard-coded strings behind these constants change.

Function Nomenclature

The following table shows PyBEL’s internal mapping from BEL functions to its own constants. This can be accessed programatically via pybel.parser.language.abundance_labels

BEL Function PyBEL Constant
a ABUNDANCE
abundance ABUNDANCE
geneAbundance GENE
g GENE
rnaAbunance RNA
r RNA
microRNAAbundance MIRNA
m MIRNA
proteinAbundance PROTEIN
p PROTEIN
biologicalProcess BIOPROCESS
bp BIOPROCESS
pathology PATHOLOGY
path PATHOLOGY
complexAbundance COMPLEX
complex COMPLEX
compositeAbundance COMPOSITE
composite COMPOSITE
reaction REACTION
rxn REACTION

Graph

PyBEL’s main data structure is a subclass of networkx.MultiDiGraph.

The graph contains metadata for the PyBEL version, the BEL script metadata, the namespace definitions, the annotation definitions, and the warnings produced in analysis. Like any networkx graph, all attributes of a given object can be accessed through the graph property, like in: my_graph.graph['my key']. Convenient property definitions are given for these attributes.

class pybel.BELGraph(name=None, version=None, description=None, data=None, **kwargs)[source]

This class represents biological knowledge assembled in BEL as a network by extending the networkx.MultiDiGraph.

The default constructor parses a BEL graph using the built-in networkx methods. For IO, see the pybel.io module

Parameters:
  • name (str) – The graph’s name
  • version (str) – The graph’s version. Recommended to use semantic versioning or YYYYMMDD format.
  • description (str) – A description of the graph
  • data – initial graph data to pass to networkx.MultiDiGraph
  • kwargs – keyword arguments to pass to networkx.MultiDiGraph
document

A dictionary holding the metadata from the “Document” section of the BEL script. All keys are normalized according to pybel.constants.DOCUMENT_KEYS

name

The graph’s name, from the SET DOCUMENT Name = "..." entry in the source BEL script

version

The graph’s version, from the SET DOCUMENT Version = "..." entry in the source BEL script

description

The graph’s description, from the SET DOCUMENT Description = "..." entry in the source BEL Script

namespace_url

A dictionary mapping the keywords used to create this graph to the URLs of the BELNS files from the DEFINE NAMESPACE [key] AS URL "[value]" entries in the definitions section.

namespace_owl

A dictionary mapping the keywords used to create this graph to the URLs of the OWL files from the DEFINE NAMESPACE [key] AS OWL "[value]" entries in the definitions section

namespace_pattern

A dictionary mapping the namespace keywords used to create this graph to their regex patterns from the DEFINE NAMESPACE [key] AS PATTERN "[value]" entries in the definitions section

annotation_url

A dictionary mapping the annotation keywords used to create this graph to the URLs of the BELANNO files from the DEFINE ANNOTATION [key] AS URL "[value]" entries in the definitions section

annotation_owl

A dictionary mapping the annotation keywords used to creat ethis graph to the URLs of the OWL files from the DEFINE ANNOTATION [key] AS OWL "[value]" entries in the definitions section

annotation_pattern

A dictionary mapping the annotation keywords used to create this graph to their regex patterns from the DEFINE ANNOTATION [key] AS PATTERN "[value]" entries in the definitions section

annotation_list

A dictionary mapping the keywords of locally defined annotations to a set of their values from the DEFINE ANNOTATION [key] AS LIST {"[value]", ...} entries in the definitions section

pybel_version

Stores the version of PyBEL with which this graph was produced as a string

warnings

Warnings are stored in a list of 4-tuples that is a property of the graph object. This tuple respectively contains the line number, the line text, the exception instance, and the context dictionary from the parser at the time of error.

add_unqualified_edge(u, v, relation)[source]

Adds unique edge that has no annotations

Parameters:
add_node_from_data(attr_dict)[source]

Converts a PyBEL node data dictionary to a canonical PyBEL node tuple and ensures it is in the graph.

Parameters:attr_dict (dict) – A PyBEL node data dictionary
Returns:The PyBEL node tuple representing this node
Return type:tuple
add_simple_node(function, namespace, name)[source]

Adds a simple node, with only a namespace and name

Parameters:
Returns:

The PyBEL node tuple representing this node

Return type:

tuple

has_edge_citation(u, v, key)[source]

Does the given edge have a citation?

get_edge_citation(u, v, key)[source]

Gets the citation for a given edge

has_edge_evidence(u, v, key)[source]

Does the given edge have evidence?

get_edge_evidence(u, v, key)[source]

Gets the evidence for a given edge

get_edge_annotations(u, v, key)[source]

Gets the annotations for a given edge

get_node_name(node)[source]

Gets the node’s name, or return None if no name

get_node_label(node)[source]

Gets the label for a given node

set_node_label(node, label)[source]

Sets the label for a given node

get_node_description(node)[source]

Gets the description for a given node

set_node_description(node, description)[source]

Sets the description for a given node

Nodes

Nodes are used to represent physical entities’ abundances. The relevant data about a node is stored in its associated dictionary in networkx. After parsing, p(HGNC:GSK3B) becomes:

{
    FUNCTION: PROTEIN,
    NAMESPACE: 'HGNC',
    NAME: 'GSK3B'
}

This section describes the structure of the data dictionaries created for each type of node available in BEL. Programatically, these dictionaries can be converted to tuples, which are used as the keys for the network with the pybel.parser.canonicalize.node_to_tuple() function.

Variants

The addition of a variant tag results in an entry called ‘variants’ in the data dictionary associated with a given node. This entry is a list with dictionaries describing each of the variants. All variants have the entry ‘kind’ to identify whether it is a post-translational modification (PTM), gene modification, fragment, or HGVS variant.

Warning

The canonical ordering for the elements of the VARIANTS list correspond to the sorted order of their corresponding node tuples using pybel.parser.canonicalize.sort_dict_list(). Rather than directly modifying the BELGraph’s structure, use pybel.BELGraph.add_node_from_data(), which takes care of automatically canonicalizing this dictionary.

HGVS Variants

For example, the node p(HGNC:GSK3B, var(p.Gly123Arg)) is represented with the following:

{
     FUNCTION: PROTEIN,
     NAMESPACE: 'HGNC',
     NAME: 'GSK3B',
     VARIANTS:  [
         {
            KIND: HGVS,
            IDENTIFIER: 'p.Gly123Arg'
         }
    ]
}

See also

Gene Substitutions

Gene substitutions are legacy statements defined in BEL 1.0. BEL 2.0 recommends using HGVS strings. Luckily, the information contained in a BEL 1.0 encoding, such as g(HGNC:APP,sub(G,275341,C)) can be automatically translated to the appropriate HGVS g(HGNC:APP, var(c.275341G>C)), assuming that all substitutions are using the reference coding gene sequence for numbering and not the genomic reference. The previous statements both produce the underlying data:

{
    FUNCTION: GENE,
    NAMESPACE: 'HGNC',
    NAME: 'APP',
    VARIANTS: [
        {
            KIND: HGVS,
            IDENTIFIER: 'c.275341G>C'
        }
    ]
}

See also

BEL 2.0 specification on gene substitutions

Protein Substitutions

Protein substitutions are legacy statements defined in BEL 1.0. BEL 2.0 recommends using HGVS strings. Luckily, the information contained in a BEL 1.0 encoding, such as p(HGNC:APP,sub(R,275,H)) can be automatically translated to the appropriate HGVS p(HGNC:APP, var(p.Arg275His)), assuming that all substitutions are using the reference protein sequence for numbering and not the genomic reference. The previous statements both produce the underlying data:

{
    FUNCTION: GENE,
    NAMESPACE: 'HGNC',
    NAME: 'APP',
    VARIANTS: [
        {
            KIND: HGVS,
            IDENTIFIER: 'p.Arg275His'
        }
    ]
}

See also

BEL 2.0 specification on protein substitutions

Truncations

Truncations in the legacy BEL 1.0 specification are automatically translated to BEL 2.0 with HGVS nomenclature. p(HGNC:AKT1, trunc(40)) becomes p(HGNC:AKT1, var(p.40*)) and is represented with the following dictionary:

{
    FUNCTION: PROTEIN,
    NAMESPACE: 'HGNC',
    NAME: 'AKT1',
    VARIANTS: [
        {
            KIND: HGVS,
            IDENTIFIER: 'p.40*'
        }
    ]
}

Unfortunately, the HGVS nomenclature requires the encoding of the terminal amino acid which is exchanged for a stop codon, and this information is not required by BEL 1.0. For this example, the proper encoding of the truncation at position also includes the information that the 40th amino acid in the AKT1 is Cys. Its BEL encoding should be p(HGNC:AKT1, var(p.Cys40*)). Temporary support has been added to compile these statements, but it’s recommended they are upgraded by reexamining the supporting text, or looking up the amino acid sequence.

See also

BEL 2.0 specification on truncations

Fragments

The addition of a fragment results in an entry called pybel.constants.VARIANTS in the data dictionary associated with a given node. This entry is a list with dictionaries describing each of the variants. All variants have the entry pybel.constants.KIND to identify whether it is a PTM, gene modification, fragment, or HGVS variant. The pybel.constants.KIND value for a fragment is pybel.constants.FRAGMENT.

Each fragment contains an identifier, which is a dictionary with the namespace and name, and can optionally include the position (‘pos’) and/or amino acid code (‘code’).

For example, the node p(HGNC:GSK3B, frag(45_129)) is represented with the following:

{
    FUNCTION: PROTEIN,
    NAMESPACE: 'HGNC',
    NAME: 'GSK3B',
    VARIANTS: [
        {
            KIND: FRAGMENT,
            FRAGMENT_START: 45,
            FRAGMENT_STOP: 129
        }
    ]
}

Additionally, nodes can have an asterick (*) or question mark (?) representing unbound or unknown fragments, respectively.

A fragment may also be unknown, such as in the node p(HGNC:GSK3B, frag(?)). This is represented with the key pybel.constants.FRAGMENT_MISSING and the value of ‘?’ like:

{
    FUNCTION: PROTEIN,
    NAMESPACE: 'HGNC',
    NAME: 'GSK3B',
    VARIANTS: [
        {
            KIND: FRAGMENT,
            FRAGMENT_MISSING: '?',
        }
    ]
}

See also

BEL 2.0 specification on proteolytic fragments (2.2.3)

Gene Modifications

PyBEL introduces the gene modification tag, gmod(), to allow for the encoding of epigenetic modifications. Its syntax follows the same style s the pmod() tags for proteins, and can include the following values:

  • M
  • Me
  • methylation
  • A
  • Ac
  • acetylation

For example, the node g(HGNC:GSK3B, gmod(M)) is represented with the following:

{
    FUNCTION: GENE,
    NAMESPACE: 'HGNC',
    NAME: 'GSK3B',
    VARIANTS: [
        {
            KIND: GMOD,
            IDENTIFIER: {
                NAMESPACE: BEL_DEFAULT_NAMESPACE,
                NAME: 'Me'
            }
        }
    ]
}

The addition of this function does not preclude the use of all other standard functions in BEL; however, other compilers probably won’t support these standards. If you agree that this is useful, please contribute to discussion in the OpenBEL community.

Protein Modifications

The addition of a post-translational modification (PTM) tag results in an entry called ‘variants’ in the data dictionary associated with a given node. This entry is a list with dictionaries describing each of the variants. All variants have the entry ‘kind’ to identify whether it is a PTM, gene modification, fragment, or HGVS variant. The ‘kind’ value for PTM is ‘pmod’.

Each PMOD contains an identifier, which is a dictionary with the namespace and name, and can optionally include the position (‘pos’) and/or amino acid code (‘code’).

For example, the node p(HGNC:GSK3B, pmod(P, S, 9)) is represented with the following:

{
    FUNCTION: PROTEIN,
    NAMESPACE: 'HGNC',
    NAME: 'GSK3B',
    VARIANTS: [
        {
            KIND: PMOD,
            IDENTIFIER: {
                NAMESPACE: BEL_DEFAULT_NAMESPACE
                NAME: 'Ph',

            },
            PMOD_CODE: 'Ser',
            PMOD_POSITION: 9
        }
    ]
}

As an additional example, in p(HGNC:MAPK1, pmod(Ph, Thr, 202), pmod(Ph, Tyr, 204)), MAPK is phosphorylated twice to become active. This results in the following:

{
    FUNCTION: PROTEIN,
    NAMESPACE: 'HGNC',
    NAME: 'MAPK1',
    VARIANTS: [
        {
            KIND: PMOD,
            IDENTIFIER: {
                NAMESPACE: BEL_DEFAULT_NAMESPACE
                NAME: 'Ph',

            },
            PMOD_CODE: 'Thr',
            PMOD_POSITION: 202
        },
        {
            KIND: PMOD,
            IDENTIFIER: {
                NAMESPACE: BEL_DEFAULT_NAMESPACE
                NAME: 'Ph',

            },
            PMOD_CODE: 'Tyr',
            PMOD_POSITION: 204
        }
    ]
}

See also

BEL 2.0 specification on protein modifications

Fusions

Fusions

Gene, RNA, protein, and miRNA fusions are all represented with the same underlying data structure. Below it is shown with uppercase letters referring to constants from pybel.constants and. For example, g(HGNC:BCR, fus(HGNC:JAK2, 1875, 2626)) is represented as:

{
    FUNCTION: GENE,
    FUSION: {
        PARTNER_5P: {NAMESPACE: 'HGNC', NAME: 'BCR'},
        PARTNER_3P: {NAMESPACE: 'HGNC', NAME: 'JAK2'},
        RANGE_5P: {
            FUSION_REFERENCE: 'c',
            FUSION_START: '?',
            FUSION_STOP: 1875

        },
        RANGE_3P: {
            FUSION_REFERENCE: 'c',
            FUSION_START: 2626,
            FUSION_STOP: '?'
        }
    }
}

See also

BEL 2.0 specification on fusions (2.6.1)

Unqualified Edges

Unqualified edges are automatically inferred by PyBEL and do not contain citations or supporting evidence.

Variant and Modifications’ Parent Relations

All variants, modifications, fragments, and truncations are connected to their parent entity with an edge having the relationship hasParent

For p(HGNC:GSK3B, var(p.Gly123Arg)), the following edge is inferred:

p(HGNC:GSK3B, var(p.Gly123Arg)) hasParent p(HGNC:GSK3B)

All variants have this relationship to their reference node. BEL does not specify relationships between variants, such as the case when a given phosphorylation is necessary to make another one. This knowledge could be encoded directly like BEL, since PyBEL does not restrict users from manually asserting unqualified edges.

List Abundances

Complexes and composites that are defined by lists. As of version 0.9.0, they contain a list of the data dictionaries that describe their members. For example complex(p(HGNC:FOS), p(HGNC:JUN)) becomes:

{
    FUNCTION: COMPLEX,
    MEMBERS: [
        {
            FUNCTION: PROTEIN,
            NAMESPACE: 'HGNC',
            NAME: 'FOS'
        }, {
            FUNCTION: PROTEIN,
            NAMESPACE: 'HGNC',
            NAME: 'JUN'
        }
    ]
}

The following edges are also inferred:

complex(p(HGNC:FOS), p(HGNC:JUN)) hasMember p(HGNC:FOS)
complex(p(HGNC:FOS), p(HGNC:JUN)) hasMember p(HGNC:JUN)

See also

BEL 2.0 specification on complex abundances

Similarly, composite(a(CHEBI:malonate), p(HGNC:JUN)) becomes:

{
    FUNCTION: COMPOSITE,
    MEMBERS: [
        {
            FUNCTION: ABUNDANCE,
            NAMESPACE: 'CHEBI',
            NAME: 'malonate'
        }, {
            FUNCTION: PROTEIN,
            NAMESPACE: 'HGNC',
            NAME: 'JUN'
        }
    ]
}

The following edges are inferred:

composite(a(CHEBI:malonate), p(HGNC:JUN)) hasComponent a(CHEBI:malonate)
composite(a(CHEBI:malonate), p(HGNC:JUN)) hasComponent p(HGNC:JUN)

Warning

The canonical ordering for the elements of the MEMBERS list correspond to the sorted order of their corresponding node tuples using pybel.parser.canonicalize.sort_dict_list(). Rather than directly modifying the BELGraph’s structure, use BELGraph.add_node_from_data(), which takes care of automatically canonicalizing this dictionary.

See also

BEL 2.0 specification on composite abundances

Reactions

The usage of a reaction causes many nodes and edges to be created. The following example will illustrate what is added to the network for

rxn(reactants(a(CHEBI:"(3S)-3-hydroxy-3-methylglutaryl-CoA"), a(CHEBI:"NADPH"), \
    a(CHEBI:"hydron")), products(a(CHEBI:"mevalonate"), a(CHEBI:"NADP(+)")))

As of version 0.9.0, the reactants’ and products’ data dictionaries are included as sub-lists keyed REACTANTS and PRODUCTS. It becomes:

{
    FUNCTION: REACTION
    REACTANTS: [
        {
            FUNCTION: ABUNDANCE,
            NAMESPACE: 'CHEBI',
            NAME: '(3S)-3-hydroxy-3-methylglutaryl-CoA'
        }, {
            FUNCTION: ABUNDANCE,
            NAMESPACE: 'CHEBI',
            NAME: 'NADPH'
        }, {
            FUNCTION: ABUNDANCE,
            NAMESPACE: 'CHEBI',
            NAME: 'hydron'
        }
    ],
    PRODUCTS: [
        {
            FUNCTION: ABUNDANCE,
            NAMESPACE: 'CHEBI',
            NAME: 'mevalonate'
        }, {
            FUNCTION: ABUNDANCE,
            NAMESPACE: 'CHEBI',
            NAME: 'NADP(+)'
        }
    ]
}

Warning

The canonical ordering for the elements of the REACTANTS and PRODUCTS lists correspond to the sorted order of their corresponding node tuples using pybel.parser.canonicalize.sort_dict_list(). Rather than directly modifying the BELGraph’s structure, use BELGraph.add_node_from_data(), which takes care of automatically canonicalizing this dictionary.

The following edges are inferred, where X represents the previous reaction, for brevity:

X hasReactant a(CHEBI:"(3S)-3-hydroxy-3-methylglutaryl-CoA")
X hasReactant a(CHEBI:"NADPH")
X hasReactant a(CHEBI:"hydron")
X hasProduct a(CHEBI:"mevalonate")
X hasProduct a(CHEBI:"NADP(+)"))

See also

BEL 2.0 specification on reactions

Edges

Design Choices

In the OpenBEL Framework, modifiers such as activities (kinaseActivity, etc.) and transformations (translocations, degradations, etc.) were represented as their own nodes. In PyBEL, these modifiers are represented as a property of the edge. In reality, an edge like sec(p(HGNC:A)) -> activity(p(HGNC:B), ma(kinaseActivity)) represents a connection between HGNC:A and HGNC:B. Each of these modifiers explains the context of the relationship between these physical entities. Further, querying a network where these modifiers are part of a relationship is much more straightforward. For example, finding all proteins that are upregulated by the kinase activity of another protein now can be directly queried by filtering all edges for those with a subject modifier whose modification is molecular activity, and whose effect is kinase activity. Having fewer nodes also allows for a much easier display and visual interpretation of a network. The information about the modifier on the subject and activity can be displayed as a color coded source and terminus of the connecting edge.

The compiler in OpenBEL framework created nodes for molecular activities like kin(p(HGNC:YFG)) and induced an edge like p(HGNC:YFG) actsIn kin(p(HGNC:YFG)). For transformations, a statement like tloc(p(HGNC:YFG), GOCC:intracellular, GOCC:"cell membrane") also induced tloc(p(HGNC:YFG), GOCC:intracellular, GOCC:"cell membrane") translocates p(HGNC:YFG).

In PyBEL, we recognize that these modifications are actually annotations to the type of relationship between the subject’s entity and the object’s entity. p(HGNC:ABC) -> tloc(p(HGNC:YFG), GOCC:intracellular, GOCC:"cell membrane") is about the relationship between p(HGNC:ABC) and p(HGNC:YFG), while the information about the translocation qualifies that the object is undergoing an event, and not just the abundance. This is a confusion with the use of proteinAbundance as a keyword, and perhaps is why many people prefer to use just the keyword p

Example Edge Data Structure

Because this data is associated with an edge, the node data for the subject and object are not included explicitly. However, information about the activities, modifiers, and transformations on the subject and object are included. Below is the “skeleton” for the edge data model in PyBEL:

{
    SUBJECT: {
        # ... modifications to the subject node. Only present if non-empty.
    },
    RELATION: POSITIVE_CORRELATION,
    OBJECT: {
        # ... modifications to the object node. Only present if non-empty.
    },
    EVIDENCE: '...',
    CITATION : {
        CITATION_TYPE: CITATION_TYPE_PUBMED,
        CITATION_REFERENCE: '...',
        CITATION_DATE: 'YYYY-MM-DD',
        CITATION_AUTHORS: 'Jon Snow|John Doe',
    },
    ANNOTATIONS: {
        'Disease': 'Colorectal Cancer',
        # ... additional annotations as key:value pairs
    }
}

Each edge must contain the RELATION, EVIDENCE, CITATION, and ANNOTATIONS entries. The CITATION must minimally contain CITATION_TYPE and CITATION_REFERENCE since these can be used to look up additional metadata.

Activities

Modifiers are added to this structure as well. Under this schema, p(HGNC:GSK3B, pmod(P, S, 9)) pos act(p(HGNC:GSK3B), ma(kin)) becomes:

{
    RELATION: POSITIVE_CORRELATION,
    OBJECT: {
        MODIFIER: ACTIVITY,
        EFFECT: {
            NAME: 'kin'
            NAMESPACE: BEL_DEFAULT_NAMESPACE
        }
    },
    CITATION: { ... },
    EVIDENCE: '...',
    ANNOTATIONS: { ... }
}

Activities without molecular activity annotations do not contain an pybel.constants.EFFECT entry: Under this schema, p(HGNC:GSK3B, pmod(P, S, 9)) pos act(p(HGNC:GSK3B)) becomes:

{
    RELATION: POSITIVE_CORRELATION,
    OBJECT: {
        MODIFIER: ACTIVITY
    },
    CITATION: { ... },
    EVIDENCE: '...',
    ANNOTATIONS: { ... }
}

Locations

Location data also is added into the information in the edge for the node (subject or object) for which it was annotated. p(HGNC:GSK3B, pmod(P, S, 9), loc(GOCC:lysozome)) pos act(p(HGNC:GSK3B), ma(kin)) becomes:

{
    SUBJECT: {
        LOCATION: {
            NAMESPACE: 'GOCC',
            NAME: 'lysozome'
        }
    },
    RELATION: POSITIVE_CORRELATION,
    OBJECT: {
        MODIFIER: ACTIVITY,
        EFFECT: {
            NAMESPACE: BEL_DEFAULT_NAMESPACE
            NAME: 'kin',
        }
    },
    EVIDENCE: '...',
    CITATION: { ... }
}

The addition of the location() element in BEL 2.0 allows for the unambiguous expression of the differences between the process of hypothetical HGNC:A moving from one place to another and the existence of hypothetical HGNC:A in a specific location having different effects. In BEL 1.0, this action had its own node, but this introduced unnecessary complexity to the network and made querying more difficult. This calls for thoughtful consideration of the following two statements:

  • tloc(p(HGNC:A), fromLoc(GOCC:intracellular), toLoc(GOCC:"cell membrane")) -> p(HGNC:B)
  • p(HGNC:A, location(GOCC:"cell membrane")) -> p(HGNC:B)

See also

BEL 2.0 specification on cellular location (2.2.4)

Translocations

Translocations have their own unique syntax. p(HGNC:YFG1) -> sec(p(HGNC:YFG2)) becomes:

{
    RELATION: INCREASES,
    OBJECT: {
        MODIFIER: TRANSLOCATION,
        EFFECT: {
            FROM_LOC: {
                NAMESPACE: 'GOCC',
                NAME: 'intracellular'
            },
            TO_LOC: {
                NAMESPACE: 'GOCC',
                NAME: 'extracellular space'
            }
        }
    },
    CITATION: { ... },
    EVIDENCE: '...',
    ANNOTATIONS: { ... }
}

See also

BEL 2.0 specification on translocations

Degradations

Degradations are more simple, because there’s no :pybel.constants.EFFECT entry. p(HGNC:YFG1) -> deg(p(HGNC:YFG2)) becomes:

{
    RELATION: INCREASES,
    OBJECT: {
        MODIFIER: DEGRADATION
    },
    CITATION: { ... },
    EVIDENCE: '...',
    ANNOTATIONS: { ... }
}

See also

BEL 2.0 specification on degradations