network.graph   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 138
rs 10
c 0
b 0
f 0
wmc 11

1 Function

Rating   Name   Duplication   Size   Complexity  
C create_nx_graph() 0 120 11
1
# -*- coding: utf-8 -*-
2
3
"""Modules for creating and analysing energy system graphs.
4
5
This file is part of project oemof (github.com/oemof/oemof). It's copyrighted
6
by the contributors recorded in the version control history of the file,
7
available from its original location oemof/oemof/graph.py
8
9
SPDX-FileCopyrightText: Simon Hilpert <>
10
SPDX-FileCopyrightText: Uwe Krien <[email protected]>
11
12
SPDX-License-Identifier: MIT
13
"""
14
15
import networkx as nx
16
17
18
def create_nx_graph(
19
    energy_system=None,
20
    remove_nodes=None,
21
    filename=None,
22
    remove_nodes_with_substrings=None,
23
    remove_edges=None,
24
):
25
    """
26
    Create a `networkx.DiGraph` for the passed energy system and plot it.
27
    See http://networkx.readthedocs.io/en/latest/ for more information.
28
29
    Parameters
30
    ----------
31
    energy_system : `oemof.solph.network.EnergySystem`
32
33
    filename : str
34
        Absolute filename (with path) to write your graph in the graphml
35
        format. If no filename is given no file will be written.
36
37
    remove_nodes: list of strings
38
        Nodes to be removed e.g. ['node1', node2')]
39
40
    remove_nodes_with_substrings: list of strings
41
        Nodes that contain substrings to be removed e.g. ['elec', 'heat')]
42
43
    remove_edges: list of string tuples
44
        Edges to be removed e.g. [('resource_gas', 'gas_balance')]
45
46
    Examples
47
    --------
48
    >>> import os
49
    >>> import pandas as pd
50
    >>> from oemof.network.network import Bus, Sink, Transformer
51
    >>> from oemof.network.energy_system import EnergySystem
52
    >>> import oemof.network.graph as grph
53
    >>> datetimeindex = pd.date_range('1/1/2017', periods=3, freq='H')
54
    >>> es = EnergySystem(timeindex=datetimeindex)
55
    >>> b_gas = Bus(label='b_gas', balanced=False)
56
    >>> bel1 = Bus(label='bel1')
57
    >>> bel2 = Bus(label='bel2')
58
    >>> demand_el = Sink(label='demand_el', inputs = [bel1])
59
    >>> pp_gas = Transformer(label=('pp', 'gas'),
60
    ...                      inputs=[b_gas],
61
    ...                      outputs=[bel1],
62
    ...                      conversion_factors={bel1: 0.5})
63
    >>> line_to2 = Transformer(label='line_to2', inputs=[bel1], outputs=[bel2])
64
    >>> line_from2 = Transformer(label='line_from2',
65
    ...                          inputs=[bel2], outputs=[bel1])
66
    >>> es.add(b_gas, bel1, demand_el, pp_gas, bel2, line_to2, line_from2)
67
    >>> my_graph = grph.create_nx_graph(es)
68
    >>> # export graph as .graphml for programs like Yed where it can be
69
    >>> # sorted and customized. this is especially helpful for large graphs
70
    >>> # grph.create_nx_graph(es, filename="my_graph.graphml")
71
    >>> [my_graph.has_node(n)
72
    ...  for n in ['b_gas', 'bel1', "('pp', 'gas')", 'demand_el', 'tester']]
73
    [True, True, True, True, False]
74
    >>> list(nx.attracting_components(my_graph))
75
    [{'demand_el'}]
76
    >>> sorted(list(nx.strongly_connected_components(my_graph))[1])
77
    ['bel1', 'bel2', 'line_from2', 'line_to2']
78
    >>> new_graph = grph.create_nx_graph(energy_system=es,
79
    ...                                  remove_nodes_with_substrings=['b_'],
80
    ...                                  remove_nodes=["('pp', 'gas')"],
81
    ...                                  remove_edges=[('bel2', 'line_from2')],
82
    ...                                  filename='test_graph')
83
    >>> [new_graph.has_node(n)
84
    ...  for n in ['b_gas', 'bel1', "('pp', 'gas')", 'demand_el', 'tester']]
85
    [False, True, False, True, False]
86
    >>> my_graph.has_edge("('pp', 'gas')", 'bel1')
87
    True
88
    >>> new_graph.has_edge('bel2', 'line_from2')
89
    False
90
    >>> os.remove('test_graph.graphml')
91
92
    Notes
93
    -----
94
    Needs graphviz and networkx (>= v.1.11) to work properly.
95
    Tested on Ubuntu 16.04 x64 and solydxk (debian 9).
96
    """
97
    # construct graph from nodes and flows
98
    grph = nx.DiGraph()
99
100
    # add nodes
101
    for n in energy_system.nodes:
102
        grph.add_node(str(n.label), label=str(n.label))
103
104
    # add labeled flows on directed edge if an optimization_model has been
105
    # passed or undirected edge otherwise
106
    for n in energy_system.nodes:
107
        for i in n.inputs.keys():
108
            weight = getattr(
109
                energy_system.flows()[(i, n)], "nominal_value", None
110
            )
111
            if weight is None:
112
                grph.add_edge(str(i.label), str(n.label))
113
            else:
114
                grph.add_edge(
115
                    str(i.label), str(n.label), weigth=format(weight, ".2f")
116
                )
117
118
    # remove nodes and edges based on precise labels
119
    if remove_nodes is not None:
120
        grph.remove_nodes_from(remove_nodes)
121
    if remove_edges is not None:
122
        grph.remove_edges_from(remove_edges)
123
124
    # remove nodes based on substrings
125
    if remove_nodes_with_substrings is not None:
126
        for i in remove_nodes_with_substrings:
127
            remove_nodes = [
128
                str(v.label) for v in energy_system.nodes if i in str(v.label)
129
            ]
130
            grph.remove_nodes_from(remove_nodes)
131
132
    if filename is not None:
133
        if filename[-8:] != ".graphml":
134
            filename = filename + ".graphml"
135
        nx.write_graphml(grph, filename)
136
137
    return grph
138