Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/galaxy/util/simplegraph.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 """ | |
| 2 Fencepost-simple graph structure implementation. | |
| 3 """ | |
| 4 # Currently (2013.7.12) only used in easing the parsing of graph datatype data. | |
| 5 | |
| 6 from collections import OrderedDict | |
| 7 | |
| 8 | |
| 9 class SimpleGraphNode(object): | |
| 10 """ | |
| 11 Node representation. | |
| 12 """ | |
| 13 | |
| 14 def __init__(self, index, **data): | |
| 15 """ | |
| 16 :param index: index of this node in some parent list | |
| 17 :type index: int | |
| 18 :param data: any extra data that needs to be saved | |
| 19 :type data: (variadic dictionary) | |
| 20 """ | |
| 21 # a bit application specific (could be 'id') | |
| 22 self.index = index | |
| 23 self.data = data | |
| 24 | |
| 25 | |
| 26 class SimpleGraphEdge(object): | |
| 27 """ | |
| 28 Edge representation. | |
| 29 """ | |
| 30 | |
| 31 def __init__(self, source_index, target_index, **data): | |
| 32 """ | |
| 33 :param source_index: index of the edge's source node in some parent list | |
| 34 :type source_index: int | |
| 35 :param target_index: index of the edge's target node in some parent list | |
| 36 :type target_index: int | |
| 37 :param data: any extra data that needs to be saved | |
| 38 :type data: (variadic dictionary) | |
| 39 """ | |
| 40 self.source_index = source_index | |
| 41 self.target_index = target_index | |
| 42 self.data = data | |
| 43 | |
| 44 | |
| 45 class SimpleGraph(object): | |
| 46 """ | |
| 47 Each node is unique (by id) and stores its own index in the node list/odict. | |
| 48 Each edge is represented as two indeces into the node list/odict. | |
| 49 Both nodes and edges allow storing extra information if needed. | |
| 50 | |
| 51 Allows: | |
| 52 multiple edges between two nodes | |
| 53 self referential edges (an edge from a node to itself) | |
| 54 | |
| 55 These graphs are not specifically directed but since source and targets on the | |
| 56 edges are listed - it could easily be used that way. | |
| 57 """ | |
| 58 | |
| 59 def __init__(self, nodes=None, edges=None): | |
| 60 # use an odict so that edge indeces actually match the final node list indeces | |
| 61 self.nodes = nodes or OrderedDict() | |
| 62 self.edges = edges or [] | |
| 63 | |
| 64 def add_node(self, node_id, **data): | |
| 65 """ | |
| 66 Adds a new node only if it doesn't already exist. | |
| 67 :param node_id: some unique identifier | |
| 68 :type node_id: (hashable) | |
| 69 :param data: any extra data that needs to be saved | |
| 70 :type data: (variadic dictionary) | |
| 71 :returns: the new node | |
| 72 """ | |
| 73 if node_id in self.nodes: | |
| 74 return self.nodes[node_id] | |
| 75 node_index = len(self.nodes) | |
| 76 new_node = SimpleGraphNode(node_index, **data) | |
| 77 self.nodes[node_id] = new_node | |
| 78 return new_node | |
| 79 | |
| 80 def add_edge(self, source_id, target_id, **data): | |
| 81 """ | |
| 82 Adds a new node only if it doesn't already exist. | |
| 83 :param source_id: the id of the source node | |
| 84 :type source_id: (hashable) | |
| 85 :param target_id: the id of the target node | |
| 86 :type target_id: (hashable) | |
| 87 :param data: any extra data that needs to be saved for the edge | |
| 88 :type data: (variadic dictionary) | |
| 89 :returns: the new node | |
| 90 | |
| 91 ..note: that, although this will create new nodes if necessary, there's | |
| 92 no way to pass `data` to them - so if you need to assoc. more data with | |
| 93 the nodes, use `add_node` first. | |
| 94 """ | |
| 95 # adds target_id to source_id's edge list | |
| 96 # adding source_id and/or target_id to nodes if not there already | |
| 97 if source_id not in self.nodes: | |
| 98 self.add_node(source_id) | |
| 99 if target_id not in self.nodes: | |
| 100 self.add_node(target_id) | |
| 101 new_edge = SimpleGraphEdge(self.nodes[source_id].index, self.nodes[target_id].index, **data) | |
| 102 self.edges.append(new_edge) | |
| 103 return new_edge | |
| 104 | |
| 105 def gen_node_dicts(self): | |
| 106 """ | |
| 107 Returns a generator that yields node dictionaries in the form: | |
| 108 { 'id': <the nodes unique id>, 'data': <any additional node data> } | |
| 109 """ | |
| 110 for node_id, node in self.nodes.items(): | |
| 111 yield {'id': node_id, 'data': node.data} | |
| 112 | |
| 113 def gen_edge_dicts(self): | |
| 114 """ | |
| 115 Returns a generator that yields node dictionaries in the form:: | |
| 116 | |
| 117 { | |
| 118 'source': <the index of the source node in the graph's node list>, | |
| 119 'target': <the index of the target node in the graph's node list>, | |
| 120 'data' : <any additional edge data> | |
| 121 } | |
| 122 """ | |
| 123 for edge in self.edges: | |
| 124 yield {'source': edge.source_index, 'target': edge.target_index, 'data': edge.data} | |
| 125 | |
| 126 def as_dict(self): | |
| 127 """ | |
| 128 Returns a dictionary of the form:: | |
| 129 | |
| 130 { 'nodes': <a list of node dictionaries>, 'edges': <a list of node dictionaries> } | |
| 131 """ | |
| 132 return {'nodes': list(self.gen_node_dicts()), 'edges': list(self.gen_edge_dicts())} |
