Mercurial > repos > shellac > guppy_basecaller
view env/lib/python3.7/site-packages/galaxy/util/simplegraph.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author | shellac |
---|---|
date | Sat, 02 May 2020 07:14:21 -0400 |
parents | |
children |
line wrap: on
line source
""" Fencepost-simple graph structure implementation. """ # Currently (2013.7.12) only used in easing the parsing of graph datatype data. from collections import OrderedDict class SimpleGraphNode(object): """ Node representation. """ def __init__(self, index, **data): """ :param index: index of this node in some parent list :type index: int :param data: any extra data that needs to be saved :type data: (variadic dictionary) """ # a bit application specific (could be 'id') self.index = index self.data = data class SimpleGraphEdge(object): """ Edge representation. """ def __init__(self, source_index, target_index, **data): """ :param source_index: index of the edge's source node in some parent list :type source_index: int :param target_index: index of the edge's target node in some parent list :type target_index: int :param data: any extra data that needs to be saved :type data: (variadic dictionary) """ self.source_index = source_index self.target_index = target_index self.data = data class SimpleGraph(object): """ Each node is unique (by id) and stores its own index in the node list/odict. Each edge is represented as two indeces into the node list/odict. Both nodes and edges allow storing extra information if needed. Allows: multiple edges between two nodes self referential edges (an edge from a node to itself) These graphs are not specifically directed but since source and targets on the edges are listed - it could easily be used that way. """ def __init__(self, nodes=None, edges=None): # use an odict so that edge indeces actually match the final node list indeces self.nodes = nodes or OrderedDict() self.edges = edges or [] def add_node(self, node_id, **data): """ Adds a new node only if it doesn't already exist. :param node_id: some unique identifier :type node_id: (hashable) :param data: any extra data that needs to be saved :type data: (variadic dictionary) :returns: the new node """ if node_id in self.nodes: return self.nodes[node_id] node_index = len(self.nodes) new_node = SimpleGraphNode(node_index, **data) self.nodes[node_id] = new_node return new_node def add_edge(self, source_id, target_id, **data): """ Adds a new node only if it doesn't already exist. :param source_id: the id of the source node :type source_id: (hashable) :param target_id: the id of the target node :type target_id: (hashable) :param data: any extra data that needs to be saved for the edge :type data: (variadic dictionary) :returns: the new node ..note: that, although this will create new nodes if necessary, there's no way to pass `data` to them - so if you need to assoc. more data with the nodes, use `add_node` first. """ # adds target_id to source_id's edge list # adding source_id and/or target_id to nodes if not there already if source_id not in self.nodes: self.add_node(source_id) if target_id not in self.nodes: self.add_node(target_id) new_edge = SimpleGraphEdge(self.nodes[source_id].index, self.nodes[target_id].index, **data) self.edges.append(new_edge) return new_edge def gen_node_dicts(self): """ Returns a generator that yields node dictionaries in the form: { 'id': <the nodes unique id>, 'data': <any additional node data> } """ for node_id, node in self.nodes.items(): yield {'id': node_id, 'data': node.data} def gen_edge_dicts(self): """ Returns a generator that yields node dictionaries in the form:: { 'source': <the index of the source node in the graph's node list>, 'target': <the index of the target node in the graph's node list>, 'data' : <any additional edge data> } """ for edge in self.edges: yield {'source': edge.source_index, 'target': edge.target_index, 'data': edge.data} def as_dict(self): """ Returns a dictionary of the form:: { 'nodes': <a list of node dictionaries>, 'edges': <a list of node dictionaries> } """ return {'nodes': list(self.gen_node_dicts()), 'edges': list(self.gen_edge_dicts())}