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